项目整合微信扫码登录功能
項目整合微信登錄功能
一、準備工作
https://open.weixin.qq.com
1、注冊
2、郵箱激活
3、完善開發者資料
4、開發者資質認證
準備營業執照,1-2個工作日審批、300元
5、創建網站應用
提交審核,7個工作日審批
6、內網穿透
ngrok的使用
7、熟悉微信登錄流程
參考文檔:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN
獲取access_token時序圖
二、后端開發
(1)生成授權URL
1、在項目用戶模塊的application.properties配置文件中添加相關配置信息
# 微信開放平臺 appid wx.open.app_id=你的appid# 微信開放平臺 appsecret wx.open.app_secret=你的appsecret# 微信開放平臺 重定向url wx.open.redirect_url=http://你的服務器名稱/api/ucenter/wx/callback2、在用戶模塊創建utils包并創建ConstantWeChatUtils常量類
@Component public class ConstantWeChatUtils implements InitializingBean {@Value("${wx.open.app_id}")private String appid;@Value("${wx.open.app_secret}")private String appsecret;@Value("${wx.open.redirect_url}")private String redirectUrl;public static String WX_OPEN_APP_ID;public static String WX_OPEN_APP_SECRET;public static String WX_OPEN_REDIRECT_URL;@Overridepublic void afterPropertiesSet() throws Exception {WX_OPEN_APP_ID = appid;WX_OPEN_APP_SECRET = appsecret;WX_OPEN_REDIRECT_URL = redirectUrl;} }3、開通內網穿透隧道,指向本地微信掃碼登錄功能所在模塊的端口號。
①登錄ngrok官網:http://www.ngrok.cc
②注冊賬號,依據個人情況申請開通隧道。
③填寫隧道相關配置
④申請成功后下載Ngrok客戶端,并啟動Ngrok
4、生成微信掃描二維碼
①訪問微信提供的固定的地址,向地址里面拼接參數,二維碼就可以生成出來
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
參數說明
| appid | 是 | 應用唯一標識 |
| redirect_uri | 是 | 請使用urlEncode對鏈接進行處理 |
| response_type | 是 | 填code |
| scope | 是 | 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即 |
| state | 是 | 用于保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用于防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數,可設置為簡單的隨機數加session進行校驗 |
②創建生成二維碼的方法(Controller)
@Controller @RequestMapping("/api/ucenter/wx") @Api(tags = "微信二維碼生成接口") @CrossOrigin public class WxApiController {@ApiOperation(value = "生成微信掃碼登錄二維碼")@GetMapping("login")public String genQrConnect() {//定義微信生成二維碼固定地址//向地址里面拼接參數//%s 相當于是占位符String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +"?appid=%s" +"&redirect_uri=%s" +"&response_type=code" +"&scope=snsapi_login" +"&state=%s" +"#wechat_redirect";try {//redirecturl地址進行urlEncode編碼String redirectUrl = ConstantWeChatUtils.WX_OPEN_REDIRECT_URL;redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");//防止csrf攻擊(跨站請求偽造攻擊)//String state = UUID.randomUUID().toString().replaceAll("-", "");//一般情況下會使用一個隨機數String state = "onlineeducation";//此處state設置的是我內網穿透中的前置域名//向%s位置傳遞參數值String formatUrl = String.format(baseUrl,ConstantWeChatUtils.WX_OPEN_APP_ID,redirectUrl,state);//重定向到拼接好的地址里面return "redirect:"+formatUrl;}catch(Exception e) {return null;}} }(2)開發回調URL
1.模塊添加依賴
<!--httpclient--> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.1</version> </dependency> <!--commons-io--> <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version> </dependency> <!--gson--> <dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.2</version> </dependency>2.在utils包中創建httpclient工具類
工具類提取地址:https://pan.baidu.com/s/19h6935qHlZ-RSVEvjTlgOw
提取碼:3wuo
3.在WxApiController中創建回調方法
@Autowired private UcenterMemberService memberService;//此處注入的為項目中用戶模塊的service/** * 1、獲取回調參數 * 2、從redis中讀取state進行比對,異常則拒絕調用 * 3、向微信的授權服務器發起請求,使用臨時票據換取access_token * 4、使用上一步獲取的openid查詢數據庫,判斷當前用戶是否已注冊,如果已注冊則直接進行登錄操作 * 5、如果未注冊,則使用openid和access_token向微信的資源服務器發起請求,請求獲取微信的用戶信息 * 5.1、將獲取到的用戶信息存入數據庫 * 5.2、然后進行登錄操作 * * @param code * @param state * @return */ @GetMapping("callback") @ApiOperation(value = "掃描成功后的回調方法") public String callback(String code,String state) {//code參數:臨時票據,隨機字符串,類似于手機驗證碼//state參數:生成二維碼傳遞state值//1 獲取code臨時票據//2 請求微信固定地址,得到acess_token和openidString baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +"?appid=%s" +"&secret=%s" +"&code=%s" +"&grant_type=authorization_code";//拼接參數baseAccessTokenUrl = String.format(baseAccessTokenUrl,ConstantWeChatUtils.WX_OPEN_APP_ID,ConstantWeChatUtils.WX_OPEN_APP_SECRET,code);try {//請求這個帶參數地址,得到acess_token和openid//使用httpclientString accessTokenResult = HttpClientUtils.get(baseAccessTokenUrl);// System.out.println("*********************accessTokenResult: "+accessTokenResult);//得到acess_token和openidGson gson = new Gson();//把accessTokenResult字符串轉換map類型HashMap accessTokenMap = gson.fromJson(accessTokenResult, HashMap.class);String access_token = (String)accessTokenMap.get("access_token");String openid = (String)accessTokenMap.get("openid");//3 拿著acess_token和openid再去請求微信固定地址,得到掃描人信息String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=%s" +"&openid=%s";baseUserInfoUrl = String.format(baseUserInfoUrl,access_token,openid);//請求地址String userInfoResult = HttpClientUtils.get(baseUserInfoUrl);HashMap userInfoMap = gson.fromJson(userInfoResult, HashMap.class);String nickname = (String)userInfoMap.get("nickname");String headimgurl = (String)userInfoMap.get("headimgurl");//4 把獲取微信掃描人信息添加數據庫里面//添加信息之前判斷,根據openid進行判斷,如果表存儲相同用戶信息不需要添加//需要給用戶設置哪些信息根據自己的表字段進行設置UcenterMember member = memberService.getUserInfoByOpenId(openid);if(member == null) {//表不存在相同用戶,進行添加member = new UcenterMember();member.setOpenid(openid);member.setNickname(nickname);member.setAvatar(headimgurl);memberService.save(member);}}catch(Exception e) {}return null; }其中accessTokenResult中得到的數據為:
userInfoResult中得到的數據為:
4.完善業務層
添加信息之前通過openid判斷用戶信息是否存在的代碼
//根據openid查詢掃碼登錄的用戶是否存在 @Override public UcenterMember getUserInfoByOpenId(String openid) {QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();wrapper.eq("openid",openid);UcenterMember member = baseMapper.selectOne(wrapper);return member; }(3)整合JWT令牌
1.加入jwt工具依賴
<!-- JWT --> <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version> </dependency>2.在utils包中創建JWT工具類
public class JwtUtils {public static final String SUBJECT = "guli";//名字隨意//秘鑰public static final String APPSECRET = "guli";//名字隨意public static final long EXPIRE = 1000 * 60 * 30; //過期時間,毫秒,30分鐘/*** 根據對象生成jwt的字符串** @param member* @return*/public static String geneJsonWebToken(UcenterMember member) {if (member == null || StringUtils.isEmpty(member.getId())|| StringUtils.isEmpty(member.getNickname())|| StringUtils.isEmpty(member.getAvatar())) {return null;}String token = Jwts.builder().setSubject(SUBJECT).claim("id", member.getId()).claim("nickname", member.getNickname()).claim("avatar", member.getAvatar()).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRE)).signWith(SignatureAlgorithm.HS256, APPSECRET).compact();return token;}/*** 根據jwt的token字符串,從字符串獲取用戶信息** @param token* @return*/public static Claims checkJWT(String token) {//claims類似于map集合Claims claims = Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();return claims;}}3.callback中生成jwt
在WxApiController.java的callback方法的最后添加如下代碼
// 生成jwt String token = JwtUtils.geneJsonWebToken(member);//存入cookie //CookieUtils.setCookie(request, response, "guli_jwt_token", token);//因為端口號不同存在蛞蝓問題,cookie不能跨域,所以這里使用url重寫 return "redirect:http://localhost:3000?token=" + token;4、前端打印token(前端采用的是NUXT服務器端渲染技術)
在layout/defaullt.vue中打印獲取的token值
export default {created() {console.log(this.$route.query.token)} }5.前端首頁面獲取路由token值,調用接口,根據token得到token里面用戶信息,返回進行顯示
(1)編寫接口,根據token字符串獲取用戶信息
@PostMapping("getUserInfoToken/{token}") @ApiOperation(value = "根據token獲取token里面的用戶信息") public R getUserInfoToken(@PathVariable String token) {Claims claims = JwtUtils.checkJWT(token);String id = (String)claims.get("id");String nickname = (String)claims.get("nickname");String avatar = (String)claims.get("avatar");UcenterMember member = new UcenterMember();member.setId(id);member.setNickname(nickname);member.setAvatar(avatar);return R.ok().data("member",member); }三、前端整合(NUXT)
創建頁面
1、注冊頁
pages/register.vue
<template><div class="main"><div class="title"><a href="/login">登錄</a><span>·</span><a class="active" href="/register">注冊</a></div> ?<div class="sign-up-container"><form action="register"><div class="input-prepend restyle"><input type="text" placeholder="你的昵稱"><i class="iconfont icon-user"/></div><div class="input-prepend restyle no-radius"><input type="text" placeholder="手機號"><i class="iconfont icon-phone"/></div><div class="input-prepend"><input type="password" placeholder="設置密碼"><i class="iconfont icon-password"/></div><div class="btn"><input type="submit" class="sign-up-button" value="注冊"></div><p class="sign-up-msg">點擊 “注冊” 即表示您同意并愿意遵守簡書<br><a target="_blank" href="http://www.jianshu.com/p/c44d171298ce">用戶協議</a>和<a target="_blank" href="http://www.jianshu.com/p/2ov8x3">隱私政策</a> 。</p></form><!-- 更多注冊方式 --><div class="more-sign"><h6>社交帳號直接注冊</h6><ul><li><a id="weixin" class="weixin" target="_blank" href="http://localhost:8004/api/ucenter/wx/login"><i class="iconfont icon-weixin"/></a></li><li><a id="qq" class="qq" target="_blank" href="#"><i class="iconfont icon-qq"/></a></li></ul></div></div></div> </template> ? <script> import '~/assets/css/sign.css' import '~/assets/css/iconfont.css' ? export default {layout: 'sign' } </script>在整合前端添加微信掃碼登錄時,注意將href請求路徑填寫為自己后臺的路徑即可。
2、登錄頁面
pages/login.vue
<template><div class="main"><div class="title"><a class="active" href="/login">登錄</a><span>·</span><a href="/register">注冊</a></div> ?<div class="sign-up-container"><form action="register"><div class="input-prepend restyle"><input type="text" placeholder="手機號"><i class="iconfont icon-phone"/></div><div class="input-prepend"><input type="password" placeholder="密碼"><i class="iconfont icon-password"/></div><div class="btn"><input type="submit" class="sign-in-button" value="登錄"></div></form><!-- 更多登錄方式 --><div class="more-sign"><h6>社交帳號登錄</h6><ul><li><a id="weixin" class="weixin" target="_blank" href="http://localhost:8004/api/ucenter/wx/login"><i class="iconfont icon-weixin"/></a></li><li><a id="qq" class="qq" target="_blank" href="#"><i class="iconfont icon-qq"/></a></li></ul></div></div> ?</div> </template> ? <script> import '~/assets/css/sign.css' import '~/assets/css/iconfont.css' ? export default {layout: 'sign' } </script>總結
以上是生活随笔為你收集整理的项目整合微信扫码登录功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python为啥爬取数据会有重复_使用p
- 下一篇: weui UI库适用范围