Vue+abp微信掃碼登陸

最近系統中要使用微信掃碼登陸,根據微信官方文檔和網絡搜索相關文獻實現了。分享給須要的人,也做爲本身的一個筆記。後端系統是基於ABP的,因此部分代碼直接使用了abp的接口,直接拷貝代碼編譯不經過。css

註冊微信開放平臺帳號

在微信開放平臺註冊,注意是開放平臺不是公衆平臺,這裏須要300元,而後申請網站應用。審覈經過後獲取到AppID和AppSecret以及登記的網站url。只有此url下的地址微信掃碼後才能回調。

具體申請條件見官方文檔。vue

生成登陸二維碼

在vue登陸頁面嵌入登陸二維碼,根據官方文檔,在頁面中放入一個div元素,二維碼就放在此元素中,注意var obj = new WxLogin必須放在mounted方法中執行,此時vue纔會把dom元素初始化掛載到dom樹,能夠參見vue官方文檔生命週期介紹。json

<template>
  <div id="login" class="login"></div>
</template>

<script>
export default {
  name: "WXLogin",
  data: function() {
    return {};
  },
  mounted() {
    this.wechatHandleClick();
    document.getElementsByTagName("iframe")[0].height="320";
    document.getElementsByTagName("iframe")[0].style.marginLeft="30px";
  },
  methods: {
    wechatHandleClick() {
      let ba64Css =
        "css代碼base64編碼";// 微信須要https的樣式路徑,這裏將樣式內容加密base64,能夠避免使用https,若是你的網站是https的能夠直接使用安官方文檔使用css文件路徑
      const appid = "你第一步申請的Appid";
      const redirect_uri = encodeURIComponent("http://*/#/login");
      var obj = new WxLogin({
        id: "login", //div的id
        appid: appid,
        scope: "snsapi_login",//固定內容
        redirect_uri: redirect_uri, //回調地址
        // href: "http://*/static/UserCss/WeChart.css" //自定義樣式連接,第三方可根據實際需求覆蓋默認樣式。        
        href: "data:text/css;base64," + ba64Css
        // state: "", //參數,可帶可不帶
        // style: "", //樣式  提供"black"、"white"可選,默認爲黑色文字描述
      });
    }
  }
};
</script>

註冊回調事件

用戶掃碼後微信會回調訪問前一步提供的redirect_uri,這裏要監控微信回調,並用微信返回的code請求後端,在後端再去訪問微信服務器獲取token及用戶openID
在回調頁面中監控路由改變事件以監控微信回調(由於個人二維碼和回調在同一個路由頁面),若是有其餘更好的方法請告訴我。後端

@Watch("$route")
  async RouteChange(newVal, oldVal) {
    await this.weixinRedirect();
  }
  // 請求微信後臺
  async weixinRedirect() {
    let code = this.$route.query.code;
    let state = this.$route.query.state;
    if (code) {
      let wxTo = {
        code,
        state
      };
      //請求後臺
      this.$http("*/WeixinRedirect",data:wxTo).then((token)=>{
          //登陸成功,把token寫入cookie
          //跳轉到主頁
            this.$router.replace({ path: "/", replace: true });
      }).catch(error => {
          //保持當前頁面
          this.$router.replace({ path: "/login", replace: true });
        });
    }
  }
}

後端接收code請求token

在appsettings.json中配置AppId和AppSecret
api

[HttpPost]
public async Task<AuthenticateResultModel> WeixinRedirect(string code, string state)
{
    if (code.IsNullOrEmpty())
    {
        throw new UserFriendlyException("微信受權失敗,請從新受權");
    }
    var appid = configuration["Authentication:Wechat:AppId"];
    var secret = configuration["Authentication:Wechat:AppSecret"];
    var url = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
    var httpClient = httpClientFactory.CreateClient();
    httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
    httpClient.Timeout = TimeSpan.FromMinutes(3);

    var resstr = await httpClient.GetStringAsync(url);
    try{
        //若是微信受權返回失敗這裏序列化不成功
      var res = JsonSerializationHelper.DeserializeWithType<WeiXinAccess_tokenResponse>(resstr);
    }catch (Exception e)
    {
        throw new UserFriendlyException("獲取微信access_token失敗");
    }
    if (res == null || res.openid.IsNullOrEmpty())
    {
        throw new UserFriendlyException("獲取微信access_token失敗");
    }
    var userId = //根據openID獲取用戶id,咱們系統要求用戶提早把微信和用戶關聯綁定,因此這裏能夠根據微信用戶的openID獲取到戶農戶id;
    //使用用戶直接登陸
    if (!userId.IsNullOrEmpty()&&long.TryParse(userId, out long id))
    {
        var user = await _userManager.GetUserByIdAsync(id);
        var loginResult = await _logInManager.LoginByUser(user);
        string accessToken = CreateAccessToken(CreateJwtClaims(loginResult.Identity));

        return new AuthenticateResultModel
        {
            AccessToken = accessToken,
            EncryptedAccessToken = GetEncrpyedAccessToken(accessToken),
            ExpireInSeconds = (int)_tokenConfiguration.Expiration.TotalSeconds,
            UserId = loginResult.User.Id
        };
    }
    throw new UserFriendlyException("微信還沒有綁定帳號,請使用帳號登陸後綁定微信。");

}

WeiXinAccess_tokenResponse類型服務器

public class WeiXinAccess_tokenResponse
{
    public string access_token { get; set; }
    public int expires_in { get; set; }
    public string refresh_token { get; set; }
    public string openid { get; set; }
    public string scope { get; set; }
    public string unionid { get; set; }
}
相關文章
相關標籤/搜索