微信登录授权
程序员文章站
2024-02-18 18:17:28
...
一、微信登录分为两类:需要用户确认的授权登录与静默授权,用户确认的授权登录因为要通过用户的个人确认,所以可以获取用户全面的信息,无论是否关注相关微信号都可以获取,静默授权是嵌套在普通网页中的授权方式,不需要用户确认,但只能获取微信用户的唯一标识openid,但有时候这种交互方式更加的友好,对于用户的简单认证还是很有用的。详细流程看代码如下:
public class NeedOAuthAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var bc = filterContext.Controller as BaseController;
if (bc == null) return;
//正式环境执行
if (SystemConfig.Instance.IsProductionEnv)
{
if (BroswerUtility.SideInWeixinBroswer(filterContext.HttpContext))
{
if (!string.IsNullOrEmpty(bc.SessionOpenId))
{
base.OnActionExecuting(filterContext);
}
else
{
bc.RedirectUrl = System.Web.HttpContext.Current.Request.Url.AbsoluteUri;
var absolutePath = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
var path = AppSettingsHelper.GetString("BackHost");
var oauthurl = OAuthApi.GetAuthorizeUrl(WeixinConfig.Instance.AppId, path + "/oauth2/UserInfoCallback", "CidTech", OAuthScope.snsapi_userinfo);
filterContext.Result = new RedirectResult(oauthurl);
}
}
else //微信外
{
filterContext.Result = new RedirectResult("/404");
}
}
base.OnActionExecuting(filterContext);
}
}
}
微信回调,两种不同的授权方式:
public class OAuth2Controller : BaseController
{
//下面换成账号对应的信息,也可以放入web.config等地方方便配置和更换
private readonly string appId = WeixinConfig.Instance.AppId;
private readonly string secret = WeixinConfig.Instance.AppSecret;
public ActionResult Index()
{
//此页面引导用户点击授权
return View();
}
/// <summary>
/// OAuthScope.snsapi_userinfo方式回调
/// </summary>
/// <param name="code"></param>
/// <param name="state"></param>
/// <returns></returns>
public ActionResult UserInfoCallback(string code, string state)
{
//Logging.Log.Info("执行UserInfoCallback成功");
if (string.IsNullOrEmpty(code))
{
return Content("您拒绝了授权!");
}
if (state != "CidTech")
{
//这里的state其实是会暴露给客户端的,验证能力很弱,这里只是演示一下
//实际上可以存任何想传递的数据,比如用户ID,并且需要结合例如下面的Session["OAuthAccessToken"]进行验证
return Content("验证失败!请从正规途径进入!");
}
OAuthAccessTokenResult result = null;
//通过,用code换取access_token
try
{
result = OAuthApi.GetAccessToken(appId, secret, code);
}
catch (Exception ex)
{
return Content(ex.Message);
}
if (result.errcode != ReturnCode.请求成功)
{
return Content("错误:" + result.errmsg);
}
//下面2个数据也可以自己封装成一个类,储存在数据库中(建议结合缓存)
//如果可以确保安全,可以将access_token存入用户的cookie中,每一个人的access_token是不一样的
//Session["OAuthAccessTokenStartTime"] = DateTime.Now;
//Session["OAuthAccessToken"] = result;
//SessionUnionId = result.unionid;
SessionOpenId = result.openid;
//因为第一步选择的是OAuthScope.snsapi_userinfo,这里可以进一步获取用户详细信息
try
{
var uij = OAuthApi.GetUserInfo(result.access_token, result.openid);
WeChatService.Instance.WeixinSubscribe(new WeChatInfo()
{
Country = uij.country,
Province = uij.province,
City = uij.city,
HeadImgurl = uij.headimgurl,
NickName = uij.nickname,
Sex = uij.sex,
OpenId = uij.openid,
UnionId = uij.unionid,
Flag = 0
});
//SessionWeChatInfomation = uij;
//建议将获取的用户信息保存到数据库以便于以后数据分析
return state == "CidTech" ? new RedirectResult(RedirectUrl) : new RedirectResult(AppSettingsHelper.GetString("RedirectUrl"));
}
catch (ErrorJsonResultException ex)
{
return Content(ex.Message);
}
}
/// <summary>
/// OAuthScope.snsapi_base方式回调
/// </summary>
/// <param name="code"></param>
/// <param name="state"></param>
/// <returns></returns>
public ActionResult BaseCallback(string code, string state)
{
if (string.IsNullOrEmpty(code))
{
return Content("您拒绝了授权!");
}
if (state != "CidTech")
{
//这里的state其实是会暴露给客户端的,验证能力很弱,这里只是演示一下
//实际上可以存任何想传递的数据,比如用户ID,并且需要结合例如下面的Session["OAuthAccessToken"]进行验证
return Content("验证失败!请从正规途径进入!");
}
//通过,用code换取access_token
var result = OAuthApi.GetAccessToken(appId, secret, code);
if (result.errcode != ReturnCode.请求成功)
{
return Content("错误:" + result.errmsg);
}
//下面2个数据也可以自己封装成一个类,储存在数据库中(建议结合缓存)
//如果可以确保安全,可以将access_token存入用户的cookie中,每一个人的access_token是不一样的
//Session["OAuthAccessTokenStartTime"] = DateTime.Now;
//Session["OAuthAccessToken"] = result;
//SessionUnionId = result.unionid;
SessionOpenId = result.openid;
//因为这里还不确定用户是否关注本微信,所以只能试探性地获取一下
try
{
//已关注,可以得到详细信息
var uij = OAuthApi.GetUserInfo(result.access_token, result.openid);
WeChatService.Instance.WeixinSubscribe(new WeChatInfo()
{
Country = uij.country,
Province = uij.province,
City = uij.city,
HeadImgurl = uij.headimgurl,
NickName = uij.nickname,
Sex = uij.sex,
OpenId = uij.openid,
UnionId = uij.unionid
});
return state == "CidTech" ? new RedirectResult(RedirectUrl) : new RedirectResult(AppSettingsHelper.GetString("RedirectUrl"));
}
catch (ErrorJsonResultException ex)
{
//未关注,只能授权,无法得到详细信息
//这里的 ex.JsonResult 可能为:"{\"errcode\":40003,\"errmsg\":\"invalid openid\"}"
return Content("用户已授权,授权Token:" + result);
}
}
}
微信活动涉及到跨服务器时,可以将授权域名改为第三服务器的方式,类似采用代理的方式,实现微信授权,然后回调本地服务器!
二、微信授权的接口调用次数,默认为2000,超过次数后,就会报503异常,微信报request error 错误时,考虑:1,授权域名是否改变,2.接口调用次数是否过限。
上一篇: CSRF(跨站请求伪造)原理与实践
下一篇: 获取url后面的参数