视频教程(使用+实现原理):https://share.weiyun.com/57hkopt 建议直接看视频

源码地址:https://github.com/bxjg1987/abpgeneralmodules

库版本.net core 3.1

我的abp版本:abp5.3 .net core 3.1

 

请先看微信小程序官方文档。下面说说abp中如何使用。原生asp.net core可以参考实现

服务端配置

1、安装nuget包

install-package bxjg.wechart -version 1.0.0

 

2、修改配置文件 abp.web.host/appsettings.json

 

 

3、修改启动配置类abp.web.host//startupauthconfigurer.cs

因为startup中是通过这个类中的静态方法注册身份验证相关服务的

 1 public static void configure(iservicecollection services, iconfiguration configuration)
 2         {
 3             var authbuilder = services.addauthentication(options =>
 4             {
 5                 options.defaultauthenticatescheme = "jwtbearer";
 6                 options.defaultchallengescheme = "jwtbearer";
 7             });
 8 
 9             if (bool.parse(configuration["authentication:jwtbearer:isenabled"]))
10             {
11                 authbuilder.addjwtbearer("jwtbearer", options =>
12                 {
13                     options.audience = configuration["authentication:jwtbearer:audience"];
14 
15                     options.tokenvalidationparameters = new tokenvalidationparameters
16                     {
17                         // the signing key must match!
18                         validateissuersigningkey = true,
19                         issuersigningkey = new symmetricsecuritykey(encoding.ascii.getbytes(configuration["authentication:jwtbearer:securitykey"])),
20 
21                         // validate the jwt issuer (iss) claim
22                         validateissuer = true,
23                         validissuer = configuration["authentication:jwtbearer:issuer"],
24 
25                         // validate the jwt audience (aud) claim
26                         validateaudience = true,
27                         validaudience = configuration["authentication:jwtbearer:audience"],
28 
29                         // validate the token expiry
30                         validatelifetime = true,
31 
32                         // if you want to allow a certain amount of clock drift, set that here
33                         clockskew = timespan.zero
34                     };
35 
36                     options.events = new jwtbearerevents
37                     {
38                         onmessagereceived = querystringtokenresolver
39                     };
40                 });
41             }
42 
43             if (bool.parse(configuration["authentication:wechartminiprogram:isenabled"]))
44             {
45                 authbuilder.addwechartminiprogram(opt =>
46                 {
47                     opt.appid = configuration["authentication:wechartminiprogram:appid"];
48                     opt.secret = configuration["authentication:wechartminiprogram:secret"];
49 
50                     opt.claimactions.mapjsonkey("nickname", "nickname");
51                     opt.claimactions.mapjsonkey("avatarurl", "avatarurl");
52                     opt.claimactions.mapjsonkey("gender", "gender");
53                     opt.claimactions.mapjsonkey("country", "country");
54                     opt.claimactions.mapjsonkey("province", "province");
55                     opt.claimactions.mapjsonkey("city", "city");
56                     opt.claimactions.mapjsonkey("language", "language");
57                 });
58             }
59         }

更多配置请参考视频

 

4、实现abp集成

找到abp.web.core/controllers/tokenauthcontroller

先注入usermanager

 

 

然后添加下面的方法

 1         [httppost]
 2         public async task<externalauthenticateresultmodel> wechartminiprogramloginasync()
 3         {
 4 
 5             //从第三方登录拿到当前用户(包含openid、sessionkey)
 6             var t = await base.httpcontext.authenticateasync(miniprogramconsts.authenticationscheme);//间接使用第三方身份验证方案获取信息
 7             //拿到openid
 8             var openid = t.principal.claims.single(c => c.type == claimtypes.nameidentifier).value;
 9             var tenancyname = gettenancynameornull();
10             //尝试做第三发登录(内部通过openid找到本地账号做登录),
11             var loginresult = await _loginmanager.loginasync(new userlogininfo(miniprogramconsts.authenticationscheme, openid, miniprogramconsts.authenticationschemedisplayname), tenancyname);
12             //根据登录结果,若成功则直接返回jwttoken 或者自动注册后返回
13             switch (loginresult.result)
14             {
15                 case abploginresulttype.success:
16                     {
17                         //更新微信用户信息
18                         foreach (var item in t.principal.claims)
19                         {
20                             await usermanager.replaceclaimasync(loginresult.user, new claim(item.type, ""), item);
21                         }
22 
23                         //返回jwttoken
24                         var accesstoken = createaccesstoken(createjwtclaims(loginresult.identity));
25                         return new externalauthenticateresultmodel
26                         {
27                             accesstoken = accesstoken,
28                             encryptedaccesstoken = getencryptedaccesstoken(accesstoken),
29                             expireinseconds = (int)_configuration.expiration.totalseconds
30                         };
31                     }
32                 case abploginresulttype.unknownexternallogin:
33                     {
34                         //若未找到关联的本地账号则自动注册,再返回jwttoken
35                         var newuser = await registerexternaluserasync(new externalauthuserinfo
36                         {
37                             provider = miniprogramconsts.authenticationscheme,
38                             providerkey = openid,
39                             name = t.principal.claims.singleordefault(c => c.type == "nickname")?.value,
40                             emailaddress = guid.newguid().tostring("n") + "@mp.com",
41                             surname = "a"
42                         });
43                         if (!newuser.isactive)
44                         {
45                             return new externalauthenticateresultmodel
46                             {
47                                 waitingforactivation = true
48                             };
49                         }
50 
51                         // try to login again with newly registered user!
52                         loginresult = await _loginmanager.loginasync(new userlogininfo(miniprogramconsts.authenticationscheme, openid, miniprogramconsts.authenticationschemedisplayname), tenancyname);
53                         if (loginresult.result != abploginresulttype.success)
54                         {
55                             throw _abploginresulttypehelper.createexceptionforfailedloginattempt(
56                                 loginresult.result,
57                                 openid,
58                                 tenancyname
59                             );
60                         }
61                         //保存微信用户信息(排出openid,因为它存储在userlogins里)
62                         await usermanager.addclaimsasync(loginresult.user, t.principal.claims.where(c=>c.type!= claimtypes.nameidentifier));
63 
64                         return new externalauthenticateresultmodel
65                         {
66                             accesstoken = createaccesstoken(createjwtclaims(loginresult.identity)),
67                             expireinseconds = (int)_configuration.expiration.totalseconds
68                         };
69                     }
70                 default:
71                     {
72                         throw _abploginresulttypehelper.createexceptionforfailedloginattempt(
73                             loginresult.result,
74                             openid,
75                             tenancyname
76                         );
77                     }
78             }
79         }

 

小程序端处理

小程序调用wx.login拿到code,然后调用wx.getuserinfo拿到用户昵称、头像、性别…..等数据

将上面的数据组成json  post提交到  我方服务器/wechart-miniprogram-signin

此时会返回一个加密的cookie字符串,小程序端需要想法从响应的cookie中拿到此字符串

用上面的字符串作为cookie post请求  我方服务器/api/tokenauth/wechartminiprogramlogin

此时服务端会返回jwttoken

后续请求跟之前的处理就一样了。