1、准备工作

1.1 现在微信开放平台注册一个账号

https://open.weixin.qq.com/

1.2 查看官方文档

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
 
  • 在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppIDAppSecret,申请微信登录且通过审核后,可开始接入流程
  • 注册帐号和申请应用都是免费的,必须要有一个线上的网站,才能审核通过(过程还是挺麻烦的),就可以使用微信的登录了
  •  
    但是如果想使用微信支付的功能,就必须认证开发者资质(认证一次300块人民币)
1.3 登录授权时序图
 
  • AppID  应用ID,唯一标识(身份证号)
  • AppSecret 应用的密钥(密码)
  • code 授权的临时凭证(例如:临时身份证)
  • access_token 接口调用凭证(例如:真正的身份证,虎符,令牌)

2、引入二维码

2.1 在Vue中进行安装
npm install vue-wxlogin
如果不是 vue 的项目,可以直接引用官方提供的 js 文件,来生成二维码
 
2.2 在Header.vue登录页面引入
 
<script>

// import wxlogin from 'vue-wxlogin'; // 引入

export default {

name: "Header",

components:{

// wxlogin // 声明引用的组件

},

2.3 引入二维码,首先定义了一个<div id="loginForm">

<!-- 登录表单-->
      <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=""
      />
      </div>

然后引入二维码

<!-- 二维码 -->
<wxlogin id="wxLoginForm" style="display:none" 
      :appid="appid" :scope="scope" :redirect_uri="redirect_uri">
</wxlogin>

在data中定义

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中定义

    // 微信登录
    goToLoginWX() {
      // 普通的登录表单隐藏
      document.getElementById("loginForm").style.display = "none";
      // 显示二维码的容器
      document.getElementById("wxLoginForm").style.display = "block";
     });
},

2.4 methods中login()方法

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中

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依赖

<!-- 需要使用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

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对象,转换为实体类

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字符串转换成实体对象,方便存和取

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

Integer register(@Param("phone") String phone, @Param("password") String password,@Param("nickname") String nickname,@Param("headimg") String headimg);
<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

Integer register( String phone, String password,String nickname,String headimg);
@Override
    public Integer register(String phone, String password, String nickname, String headimg) {
        return userDao.register(phone,password,nickname,headimg);
    }

3.6 lagou-edu-web

Integer register( String phone, String password,String nickname,String headimg);

 WxLoginController

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;
    }

}

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

Logo

前往低代码交流专区

更多推荐