Java快速对接微信登录

1.微信登录

微信登录属于第三方登录,和普通的账号密码登陆的最大的优点为方便快捷,且用户的基数比较大,

2.基于OAuth2.0下的微信登录

OAuth2.0是在客户端和服务端之间有一个授权层,用来将用户和客户端进行分开客户端登录授权层使用的是令牌,意思是给了多少的权限也就只能有多少的权限之类的资源

OAuth的四种模式

A-授权码模式:

你要去学校,学校有保安把大门守着,你先去找你的班主任说你要进学校,你班主任给你一个code,你把这个code去保安看,保安知道了,给你大门的钥匙(token)你拿到这个token就进入了学校

B-简化模式

就是你直接去找保安,他直接就把token给你,你拿到这个token就去开门去进入

一般是用于第三方单页面应用

C-密码模式

给你账号和密码你去开门,

这种是用于第一方的单页面应用以及第一方的原生app (内部使用)

D-客户端模式

你是个人就直接进入学校

所有最安全的模式是授权码模式

微信登录用的也是授权码模式

3.准备工作--以开发网站为案列

你要先打开微信开发平台,

进行相关的注册和申请的步骤

创建网站

获取到该网站的APPID 和APPSECRET  回调域(如果在公司,这里是直接找公司拿即可)

 

大致流程图如下

4.实现步骤

A-获取code

前端进行调用获取到code给后端进行传入

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

B-根据code进行发送http请求获取到token和appid

这是请求的链接,对应的填入要的数据即可

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

 

我这里是把这个请求的链接进行封装为一个枚举,然后在进行数据的替换

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

C-发送数据进行获取到返回的数据

这里返回的数据我进行了一个对象来进行接受,在进行json数据转实体对象的转化

/*发送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-将数据进行返回给前端即可,进行登录

5.其他步骤

如果你感觉微信登录就这样结束,那就错了,上面只是实现了第一次登录,问题来了

如果第二次,第n次登录的时候怎么办,这么实现免密登录?

5.1设计数据库

要知道是否是第一次还是第二次,那么就要在你的数据库留下东西来证明

这里我把登录成功之后会返回一些东西进行作为字段放在数据库

5.2验证是否存在---(存在)

当微信登录成功返回数据

拿出里面的数据openid去本地数据去查询有无这个包含该字段的对象

----(这里是存在就进行免密登录)

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创建自己程序端的用户

其实你的程序登录成功进入你的程序里,表面是登录微信成功就进入了,实际还有一步当登录成功就创建自己程序端的用户,(本意就是使用你的程序端的用户进入程序)

自己程序端用户:意思是通过比如手机号注册,短信注册,账号密码注册等;而不是第三方的用户

这大致是我程序的用户数据表,这里是只有你微信登录成功,我拿到你微信放回的资料。先进行创建一个装微信对象的表里面去,在对于的创建一个本地程序用户

 

5.4验证是否存在--(不存在)

当不存在,拿就要就要进行创建本地用户,和创建微信用户

这里需要给正在登录的用户跳转到本地用户注册的页面,拿就要告诉前端验证不存在进行跳转,所有这里我直接把验证失败消息放回,并且把openid和token一起带回

 // 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);

这里是通过Ajax后置拦截器(后面有时间写4大拦截器)跳转到注册页面(在这里简称callback页面)

在callback页面用户进行手机号注册,

大致页面就是获取用户的手机号

 

 

说一下为什么这里明明说是微信登录,又在手机号登录

因为他是第一次登录,所有我要给他进行新建一个本地用户对象,我的本地用户对象里面的字段有个手机号(为了后面的业务)所有我这里可以先获取到他的手机号

当点击注册按钮之后的操作

前端携带上openid和token手机号,到后端

这里大致说一下步骤

A-先把前端给的数据进行基本的校验

B-拿到手机去本地用户表查询有无对象

C-又本地对象,我就直接创建微信用户表的对象即可

D-没有就根据这个手机号去创建本地对象在在对应的创建出微信对象

E-进行免密登录,把相关的信息进行封装为map放回前端即可

以下是相关的代码

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

当这里不管是第一次还是第n次的对于的步骤都有

以下是所有的大致的步骤流程图

图太长分为两节截图

完整的图在下面的链接

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

 

 欢迎进行学习交流,不足之处请指出,喜欢麻烦点赞+收藏,谢谢各位大佬了

 

  • 3
    点赞
  • 11
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页
评论

打赏作者

是老薛啊

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值