Loading... **1、准备工作** **1.1 现在微信开放平台注册一个账号** [https://open.weixin.qq.com/](https://open.weixin.qq.com/) **1.2 查看官方文档** https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html * 在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程 * 注册帐号和申请应用都是免费的,必须要有一个线上的网站,才能审核通过(过程还是挺麻烦的),就可以使用微信的登录了 * 但是如果想使用微信支付的功能,就必须认证开发者资质(认证一次300块人民币) **1.3 登录授权时序图** * **AppID ** 应用ID,唯一标识(身份证号) * **AppSecret ** 应用的密钥(密码) * **code ** 授权的临时凭证(例如:临时身份证) * **access_token ** 接口调用凭证(例如:真正的身份证,虎符,令牌) ![](https://img-blog.csdnimg.cn/20210426122527251.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ5Njc2Mw==,size_16,color_FFFFFF,t_70) **2、引入二维码** **2.1 在Vue中进行安装** > **npm install vue-wxlogin** 如果不是 vue 的项目,可以直接引用官方提供的 js 文件,来生成二维码 2.2 在Header.vue登录页面引入 ```javascript hljs <script> // import wxlogin from 'vue-wxlogin'; // 引入 export default { name: "Header", components:{ // wxlogin // 声明引用的组件 }, ``` 2.3 引入二维码,首先定义了一个<div id="loginForm"> ```html hljs language-xml <!-- 登录表单--> <div id="loginForm"> <el-form> <el-form-item> <h1 style="font-size:30px;color:#00B38A">拉勾</h1> </el-form-item> <el-form-item> <el-input v-model="phone" placeholder="请输入常用手机号..."></el-input> </el-form-item> <el-form-item> <el-input v-model="password" placeholder="请输入密码..."></el-input> </el-form-item> </el-form> <el-button style="width:100%;margin:0px auto;background-color: #00B38A;font-size:20px" type="primary" @click="login">确 定</el-button> <p></p> <!-- 微信登录图标 --> <img @click="goToLoginWX" src="http://www.lgstatic.com/lg-passport-fed/static/pc/modules/common/img/icon-wechat@2x_68c86d1.png" alt="" style=""> </div> ``` 然后引入二维码 ```javascript hljs <!-- 二维码 --><wxlogin id="wxLoginForm" style="display:none" :appid="appid" :scope="scope" :redirect_uri="redirect_uri"></wxlogin> ``` 在data中定义 ```javascript hljs data() { return { isLogin: false, // 登录状态,true:已登录,false:未登录 userDTO:null, // 用来保存登录的用户信息 isHasNewMessage: false, // 是否有新的推送消息 dialogFormVisible: false, // 是否显示登录框,true:显示,false:隐藏 phone: "", // 双向绑定表单 手机号 password: "", // 双向绑定表单 密码 appid:"数据", // 应用唯一标识,在微信开放平台提交应用审核通过后获得 scope:"snsapi_login", // 应用授权作用域,网页应用目前仅填写snsapi_login即可 redirect_uri:"数据", //重定向地址,(回调地址) }; }, ``` 在methods中定义 ```javascript hljs // 微信登录 goToLoginWX() { // 普通的登录表单隐藏 document.getElementById("loginForm").style.display = "none"; // 显示二维码的容器 document.getElementById("wxLoginForm").style.display = "block"; });}, ``` **2.4 methods中login()方法** ```javascript hljs login(){ // 前去登录 return this.axios .get("http://localhost:80/user/login" , { params:{ phone:this.phone, password:this.password, nickname:"", headimg:"" } }) .then( (result)=>{ console.log( result ); this.dialogFormVisible = false ; //关闭登录框 this.userDTO = result.data; // 保存返回数据中的用户对象信息 this.isLogin = true; // 更新登录状态 localStorage.setItem("user", JSON.stringify(this.userDTO)); // 将登录成功的对象信息保存到本地储存中 } ) .catch( (error)=>{ this.$message.error("登录失败!"); }); }, ``` ** 2.5 created中** ```javascript hljs created(){ // 当刷新页面,组件创建成功之后,立刻检测本地储存中是否存在用户对象 this.userDTO = JSON.parse( localStorage.getItem("user") ); if(this.userDTO != null){ this.isLogin = true; // 已登录 }else{ // 去检测微信是否登录过 this.axios .get("http://localhost:80/user/checkWxStatus") .then( (result)=>{ this.userDTO = result.data; this.phone = this.userDTO.content.phone; this.password = this.userDTO.content.password; this.login();// 走普通登录 }) .catch( (error)=>{ //this.$message.error("登录失败!"); }); } }, ``` 修改HOSTS文件 文件位置: C:\Windows\System32\drivers\etc\hosts 回调默认指定的是 80 端口,别忘记将 tomcat 的 8003 端口修改成 80 > 127.0.0.1 www . pinzhi365 . com **3、IDEA代码** **3.1 lagou-edu-web中pom.xml依赖** ```XML hljs <!-- 需要使用HttpServletRequest获得参数 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> <!-- 需要使用HttpClient发出请求 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.12</version> </dependency> ``` **3.2 在commons中封装HttpClientUtil** ```java hljs package commons; import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.utils.URIBuilder;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils; import java.net.URI;import java.util.Map; /** * @Description: httpclient的封装工具类 */public class HttpClientUtil { public static String doGet(String url) { return doGet(url,null); } /** * get请求,支持request请求方式,不支持restfull方式 * * @param url 请求地址 * @param param 参数 * @return 响应的字符串 */ public static String doGet(String url, Map<String, String> param) { // 创建httpclient对象 CloseableHttpClient httpClient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response =null; try { // 创建url URIBuilder builder = new URIBuilder(url); if (param != null) { // 在url后面拼接请求参数 for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); // 创建http get请求 HttpGet httpGet = new HttpGet(uri); // 执行请求 response = httpClient.execute(httpGet); // 从响应对象中获取状态码(成功或失败的状态) int statusCode = response.getStatusLine().getStatusCode(); System.out.println("响应的状态 = " + statusCode); // 200表示响应成功 if (statusCode == 200) { // 响应的内容字符串 resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); } } catch (Exception e) { e.printStackTrace(); }finally{ // 释放资源 try { if (response != null) { response.close(); } httpClient.close(); } catch (Exception e) { e.printStackTrace(); } } return resultString; }} ``` **3.3 定义从微信返回的数据对象——定义Token对象,转换为实体类** ```java hljs package entity; /** * @Description: 令牌实体类 */public class Token { private String access_token ;//接口调用凭证 private String expires_in;// access_token接口调用凭证超时时间,单位(秒) private String refresh_token;// 用户刷新access_token private String openid;// 授权用户唯一标识 private String scope;// 用户授权的作用域,使用逗号(,)分隔 private String unionid;// 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。 public String getAccess_token() { return access_token; } public void setAccess_token(String access_token) { this.access_token = access_token; } public String getExpires_in() { return expires_in; } public void setExpires_in(String expires_in) { this.expires_in = expires_in; } public String getRefresh_token() { return refresh_token; } public void setRefresh_token(String refresh_token) { this.refresh_token = refresh_token; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; } public Token() { } public Token(String access_token, String expires_in, String refresh_token, String openid, String scope, String unionid) { this.access_token = access_token; this.expires_in = expires_in; this.refresh_token = refresh_token; this.openid = openid; this.scope = scope; this.unionid = unionid; }} ``` **3.3 定义WxUser——将json格式的user字符串转换成实体对象,方便存和取** ```java hljs package entity; /** * @Description: 微信的用户信息 */public class WxUser { private String openid;// 普通用户的标识,对当前开发者帐号唯一 private String nickname;// 普通用户昵称 private String sex;// 普通用户性别,1为男性,2为女性 private String province;// 普通用户个人资料填写的省份 private String city;// 普通用户个人资料填写的城市 private String country;// 国家,如中国为CN private String headimgurl;// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空 private String privilege;// 用户特权信息,json数组,如微信沃卡用户为(chinaunicom) private String unionid;// 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。 public WxUser() { } public WxUser(String openid, String nickname, String sex, String province, String city, String country, String headimgurl, String privilege, String unionid) { this.openid = openid; this.nickname = nickname; this.sex = sex; this.province = province; this.city = city; this.country = country; this.headimgurl = headimgurl; this.privilege = privilege; this.unionid = unionid; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getHeadimgurl() { return headimgurl; } public void setHeadimgurl(String headimgurl) { this.headimgurl = headimgurl; } public String getPrivilege() { return privilege; } public void setPrivilege(String privilege) { this.privilege = privilege; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; }} ``` **3.4 lagou-edu-dao** ```java hljs Integer register(@Param("phone") String phone, @Param("password") String password,@Param("nickname") String nickname,@Param("headimg") String headimg); ``` ```XML hljs <insert id="register"> insert into `user` (`name`,portrait,phone,password,create_time,update_time) values (#{nickname},#{headimg},#{phone},#{password},sysdate(),sysdate())</insert> ``` **3.5 lagou-edu-service** ```java hljs Integer register( String phone, String password,String nickname,String headimg); ``` ```java hljs @Override public Integer register(String phone, String password, String nickname, String headimg) { return userDao.register(phone,password,nickname,headimg); } ``` **3.6 lagou-edu-web** ```java hljs Integer register( String phone, String password,String nickname,String headimg); ``` ** WxLoginController** ```java hljs package com.lagou.wx; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;import com.alibaba.dubbo.config.annotation.Reference;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.lagou.entity.User;import com.lagou.entity.UserDTO;import com.lagou.user.UserService;import commons.HttpClientUtil;import entity.Token;import entity.WxUser;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException; /** * @Description: */@RestController@RequestMapping("user")public class WxLoginController { @Reference // 远程消费 private UserService userService; private UserDTO dto = null; // 是否用微信登录成功,dto为null,则尚未登录 @GetMapping("wxlogin") public String wxlogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 微信官方发给我们一个临时凭证 String code = request.getParameter("code"); System.out.println("【临时凭证】code = " + code); // 2. 通过code,去微信官方申请一个正式的token(令牌) String getTokenByCode_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxd99431bbff8305a0&secret=60f78681d063590a469f1b297feff3c4&code=" + code + "&grant_type=authorization_code"; String tokenString = HttpClientUtil.doGet(getTokenByCode_url); System.out.println("tokenString = " + tokenString); // 将json格式的token字符串转换成实体对象,方便存和取 Token token = JSON.parseObject(tokenString, Token.class); // 3. 通过token,去微信官方获取用户的信息 String getUserByToken_url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + token.getAccess_token() + "&openid=" + token.getOpenid(); String userinfoString = HttpClientUtil.doGet(getUserByToken_url); System.out.println("userinfoString = " + userinfoString); // 将json格式的user字符串转换成实体对象,方便存和取 WxUser wxUser = JSON.parseObject(userinfoString, WxUser.class); System.out.println("微信昵称 = " + wxUser.getNickname()); System.out.println("微信头像 = " + wxUser.getHeadimgurl()); // 拉勾的业务流程! 需要 手机号(wxUser.getUnionid())和密码(wxUser.getUnionid()),头像和昵称 User user = null; dto = new UserDTO(); // 检测手机号是否注册 Integer i = userService.checkPhone(wxUser.getUnionid()); if(i == 0){ // 未注册,自动注册并登录 userService.register(wxUser.getUnionid(), wxUser.getUnionid(),wxUser.getNickname(),wxUser.getHeadimgurl()); dto.setMessage("手机号尚未注册,系统已帮您自动注册,请牢记密码!"); user = userService.login(wxUser.getUnionid(), wxUser.getUnionid()); }else{ user = userService.login(wxUser.getUnionid(), wxUser.getUnionid()); if(user == null){ dto.setState(300); //300表示失败 dto.setMessage("帐号密码不匹配,登录失败!"); }else{ dto.setState(200); //200表示成功 dto.setMessage("登录成功!"); } } dto.setContent(user); response.sendRedirect("http://localhost:8080"); return null; } @GetMapping("checkWxStatus") public UserDTO checkWxStatus(){ return this.dto; } @GetMapping("logout") public Object logout(){ this.dto = null; return null; } } ``` 最后修改:2022 年 03 月 15 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏