Java quick docking WeChat login

1. WeChat login

WeChat login is a third-party login, and the biggest advantage of logging in with an ordinary account and password is that it is convenient and quick, and the user base is relatively large.

2. WeChat login based on OAuth2.0

OAuth2.0 is an authorization layer between the client and the server, which is used to separate the user from the client. The client login authorization layer uses tokens, which means that there are only as many permissions as are given. Resources like permissions

Four modes of OAuth

A-Authorization code mode:

You are going to school, the school has security guards guarding the gate, you first go to your head teacher and tell you that you want to enter the school, your head teacher gives you a code, you show this code to the security guard, the security guard knows and gives you the key to the gate (token) When you get this token, you can enter the school

B-simplified mode

That is, you go directly to the security guard, and he will give you the token directly. When you get the token, you can open the door and enter

Generally used for third-party single-page applications

C-cipher mode

Give you your account number and password, and you go to open the door.

This is for 1st party single page applications and 1st party native apps (internal use)

D-client mode

You go directly to the school as an individual

The most secure mode of all is the authorization code mode

WeChat login also uses the authorization code mode

3. Preparatory work - take the development of the website as a case

You need to open the WeChat development platform first,

Steps to carry out related registration and application

Create a website

Obtain the APPID and APPSECRET callback domain of the website (if you are in the company, you can get it directly from the company here)

 

The general flow chart is as follows

4. Implementation steps

A-Get the code

The front end makes a call to get the code to the back end to pass in

public AjaxResult wechat(Map<String, String> map) {
        // 1.接收code,做校验
        String code = map.get("code");

B- Send http request according to code to get token and appid

This is the requested link, just fill in the required data

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

 

I am here to encapsulate the link of this request as an enumeration, and then replace the data

 // 2.根据code从微信去获取token + openId
        String getToken = RegisterUtils.getToken
                .replace("APPID", RegisterUtils.APPID)
                .replace("SECRET", RegisterUtils.SECRET)
                .replace("CODE", code);

C-Send data to get the returned data

I have made an object to accept the data returned here, and I am converting json data to entity objects

/*发送Http获取到的是Stirng类型*/

        String httpGet = HttpClientUtils.httpGet(getToken);
        /*把String类型用JSON对象来接受一波*/
        JSONObject jsonObject = JSONObject.parseObject(httpGet);
        /*把里面的openid 和token拿出来*/
        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

D- Just return the data to the front end and log in

5. Additional steps

If you feel that the WeChat login is over like this, it is wrong, the above is only the first login, the problem is coming

What if it is the second or nth time to log in, so as to achieve password-free login?

5.1 Design database

To know if it's the first time or the second time, leave something in your database to prove it

Here I put something that will be returned after successful login as a field in the database

5.2 Verify existence --- (exists)

When the WeChat login is successful, return data

Take out the data inside openid and go to the local data to check whether there is an object containing this field

----(Here is password-free login if it exists)

String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
        // 3.根据openId查询本地的t_wxuser,看是否曾今已经扫码过
        Wxuser wxuser = wxuserMapper.loadByOpenId(openid);
        // 3.1. 有值且t_wxuser表中的user_id有值 曾今已经扫过,本次是第二...N扫码
        if (wxuser != null && wxuser.getUserId() != null) {

            /*以下是免密登录*/
            Logininfo logininfoTmp = logininfoMapper.loadByUserId(wxuser.getUserId());

5.3 Creating your own terminal user

In fact, your program has successfully logged in and entered your program. On the surface, you have entered after successfully logging in to WeChat. In fact, there is another step to create your own terminal user when you successfully log in. (The original intention is to use your terminal user to enter the program)

User of own terminal: means registering through mobile phone number, SMS, account and password, etc.; not a third-party user

This is roughly the user data table of my program. Here is the information that I got back from your WeChat only if you successfully logged in on WeChat. First create a table containing WeChat objects, and then create a local program user for it

 

5.4 Verify whether it exists -- (does not exist)

When it does not exist, it is necessary to create a local user and create a WeChat user

Here it is necessary to redirect the logged-in user to the local user registration page, and to tell the front-end verification that there is no such thing as a jump. Here, I directly put back the verification failure message, and bring back the openid and token together.

 // 3.2. 没有,需要走微信绑定流程
            HashMap<String, String> map2 = new HashMap<>();
            map2.put("accessToken", access_token);
            map2.put("openid", openid);
            // 需要返回:token + openId

            return new AjaxResult().setSuccess(false).setResultObj(map2);

Here is to jump to the registration page (referred to as the callback page here) through the Ajax post-interceptor (there will be time to write 4 major interceptors later)

On the callback page, the user registers with a mobile phone number,

The general page is to get the user's mobile phone number

 

 

Let me tell you why it is clearly said to be a WeChat login, and then log in with a mobile phone number

Because he is logging in for the first time, I need to create a new local user object for him. There is a mobile phone number in the field of my local user object (for later business), so I can get his mobile phone number first.

Actions after clicking the register button

The front end carries openid and token mobile phone number to the back end

Here are the steps

A- First perform basic verification on the data given by the front end

B- Get the mobile phone and go to the local user table to check whether there is an object

C- and local object, I can directly create the object of WeChat user table

D- If not, create a local object based on the phone number and create a corresponding WeChat object

E- For password-free login, encapsulate the relevant information into a map and put it back on the front end

Here is the relevant code

public Map<String, Object> binderWechat(BinderDto dto) {
        /*先进行基本的校验*/
        if (StringUtils.isEmpty(dto.getPhone()) ||
                StringUtils.isEmpty(dto.getVerifyCode()) ||
                StringUtils.isEmpty(dto.getAccessToken()) ||
                StringUtils.isEmpty(dto.getOpenId())) {
            throw new MyException("参数不能为空");
        }
        /*校验手机验证码是否输入成功*/
        String keyTmp = RegisterUtils.binder + dto.getPhone();
        Object codeTmp = redisTemplate.opsForValue().get(keyTmp);
        /*校验验证码是否失效*/
        if (codeTmp == null) {
            throw new MyException("验证码已经失效,请重新获取");
        }
        if (!dto.getVerifyCode().equalsIgnoreCase(codeTmp.toString().split(":")[0])) {
            throw new MyException("验证码不一致");
        }
        /*利用手机号在t_usr表进行查询,看是否有这个user
         * 为什么不查t_logininfo表,是因为要查的话还有加一个type建,这个前端的,后端没有*/
        User user = userMapper.loadByPhone(dto.getPhone());
        Logininfo logininfo = null;
        if (user == null) {
            /*就要先进行保存这个创建一个user表*/
            user = dto2User(dto);
            /*这里把模板usercopy给logininfo*/
            logininfo = user2Logininfo(user);
            logininfoMapper.save(logininfo);
            System.out.println(logininfo.getId());
            /*user还有一个关于logininfo的外键*/
            user.setLogininfoId(logininfo.getId());
            userMapper.save(user);
        }
        /*进行创建一个wxuser表*/
        /*当了这里是怎么样都会有一个user表生成的*/
        /*利用http  根据token + openId 发送到微信进行拿到数据*/
        String getWxUSER = RegisterUtils.getWxUSER
                .replace("ACCESS_TOKEN", dto.getAccessToken()
                        .replace("OPENID", dto.getOpenId()));
        /*根据这个路径去wx那用户的资源*/
        String httpGet = HttpClientUtils.httpGet(getWxUSER);
        /*利用JSONOBject工具进行转换为对象和接受*/
        Wxuser wxuser = JSONObject.parseObject(httpGet, Wxuser.class);
        /*进行这个wxuser表外键关于user外键的填入*/
        wxuser.setUserId(user.getId());
        /*把这个wxuser进行保存到数据库*/
        wxuserMapper.save(wxuser);
        /*设置昵称*/
        user.setUsername(wxuser.getNickname());
        userMapper.update(user);
        logininfo.setUsername(wxuser.getNickname());
        logininfoMapper.update(logininfo);
        /*在进行免密登录*/
        Logininfo logininfoTmp = logininfoMapper.loadByUserId(wxuser.getUserId());
        /*String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, logininfoTmp, 30, TimeUnit.MINUTES);
        *//*在进行把这个k值和v值封装成map给前端返回回去*//*
        Map<String, Object> map1 = new HashMap<>();
        map1.put("token", token);
        logininfoTmp.setSalt(null);
        logininfoTmp.setPassword(null);
        map1.put("logininfo", logininfoTmp);
        return map1;*/
        return loginSuccessJwtHandler(logininfoTmp);
    }

When here, whether it is the first time or the nth time, there are steps for the

The following is a rough flow chart of all the steps

The picture is too long to be divided into two screenshots

The full graph is at the link below

https://www.processon.com/diagraming/62f60df1079129071a2b366f

 

 Welcome to study and exchange, please point out the shortcomings, if you like it, please like + bookmark, thank you guys

 

Guess you like

Origin blog.csdn.net/m0_67601895/article/details/126281761