IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> YYGH-6-微信登录 -> 正文阅读

[Java知识库]YYGH-6-微信登录

微信登录

OAuth2

OAuth主要角色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-12GDjZFr-1655189829138)(C:\Users\86157\AppData\Local\Temp\1655184328495.png)]

现代微服务中系统微服务化以及应用的形态和设备类型增多,不能用传统的登录方式

核心的技术不是用户名和密码,而是token,由AuthServer颁发token,用户使用token进行登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIXwbTIQ-1655189829140)(C:\Users\86157\AppData\Local\Temp\1655184374095.png)]

前期准备

这个是微信登录的开发平台

微信开放平台:https://open.weixin.qq.com

授权的流程

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN ,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pxwqopxv-1655189829140)(C:\Users\86157\AppData\Local\Temp\1655184453682.png)]

我们现在需要将二维码内嵌到网页当中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QGBk33YD-1655189829141)(C:\Users\86157\AppData\Local\Temp\1655184628715.png)]

生成二维码

getLoginParam() {
  return request({
    url: `${api_name}/getLoginParam`,
    method: `get`,
  })
}

这是发送请求的js

后端写一个接口来接收这个

//1.生成微信二维码
//返回生成二维码需要的参数
@GetMapping("getLoginParam")
@ResponseBody
public Result getQrConnect() {
    try {
        Map<String, Object> map = new HashMap<>();
        map.put("appid", ConstantWxPropertiesUtils.WX_OPEN_APP_ID);
        map.put("scope", "snsapi_login");
        String wxOpenRedirectUrl = ConstantWxPropertiesUtils.WX_OPEN_REDIRECT_URL;
        wxOpenRedirectUrl = URLEncoder.encode(wxOpenRedirectUrl, "utf-8");
        map.put("redirectUri", wxOpenRedirectUrl);
        map.put("state", System.currentTimeMillis() + "");
        return Result.ok(map);
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
    }
}

Controller用到的帮助类

@Component
public class ConstantWxPropertiesUtils 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;

    @Value("${yygh.baseUrl}")
    private String yyghBaseUrl;

    public static String WX_OPEN_APP_ID;
    public static String WX_OPEN_APP_SECRET;
    public static String WX_OPEN_REDIRECT_URL;

    public static String YYGH_BASE_URL;

    @Override
    public void afterPropertiesSet() throws Exception {
        WX_OPEN_APP_ID = appId;
        WX_OPEN_APP_SECRET = appSecret;
        WX_OPEN_REDIRECT_URL = redirectUrl;
        YYGH_BASE_URL = yyghBaseUrl;
    }

}

properties配置类

# 微信登录的配置文件
wx.open.app_id=wxed9954c01bb89b47
wx.open.app_secret=a7482517235173ddb4083788de60b90e
wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback
yygh.baseUrl=http://localhost:3000

vue前端

weixinLogin() {
  this.dialogAtrr.showLoginType = 'weixin'

  weixinApi.getLoginParam().then(response => {
    var obj = new WxLogin({
      self_redirect:true,
      id: 'weixinLogin', // 需要显示的容器id
      appid: response.data.appid, // 公众号appid wx*******
      scope: response.data.scope, // 网页默认即可
      redirect_uri: response.data.redirectUri, // 授权成功后回调的url
      state: response.data.state, // 可设置为简单的随机数加session用来校验
      style: 'black', // 提供"black"、"white"可选。二维码的样式
      href: '' // 外部css文件url,需要https
    })
  })
},

这样就可以生成二维码了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCHV9bvZ-1655189829142)(C:\Users\86157\AppData\Local\Temp\1655185533504.png)]

虽然说现在有二维码了但是现在在手机上登录之后也不好进行校验,会报错404

登录逻辑

第一步从回调url中取出code

wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback

通过配置文件当中的这个描述我们可以知道现在在扫描完二维码之后会回调这个方法,于是我们来写一下这个方法.

我们的需求是扫描以后获得用户昵称,还有openid存放到数据库中

在官方文档当中我们知道了,回调函数是通过Get请求提交的,同时还附带了2个参数code和state

code=CODE&state=STATE

于是我们的方法就写成这样

//0.微信扫描后回调的方法
@GetMapping("callback")
public String callback(String code, String state) throws UnsupportedEncodingException {
    
}

第二步通过code获取access_token

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7B1TeQbY-1655189829143)(C:\Users\86157\AppData\Local\Temp\1655186508267.png)]

第三步通过access_token获取登录人的信息

下面我们来在业务层中实现这些

//0.微信扫描后回调的方法
@GetMapping("callback")
public String callback(String code, String state) throws UnsupportedEncodingException {
    log.info("code为" + code);
    log.info("state为" + state);
    //获取code
    //拿着code和微信id和密钥,请求微信的固定地址
    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
    String accesstokenInfo = restTemplate.getForObject(url, String.class, ConstantWxPropertiesUtils.WX_OPEN_APP_ID, ConstantWxPropertiesUtils.WX_OPEN_APP_SECRET, code);
    log.info("accesstokenInfo为" + accesstokenInfo);
    //把accesstokenInfo封装成一个json对象
    JSONObject jsonObject = JSONObject.parseObject(accesstokenInfo);
    String accessToken = jsonObject.getString("access_token");
    String openid = jsonObject.getString("openid");
    UserInfo userInfo = userInfoService.selectByOpenid(openid);
    //判断现在是否已经有了这个微信用户
    if (userInfo == null) {
        //拿着accessToken,openid请求微信地址得到扫描人的信息
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}";
        String userVoInfo = restTemplate.getForObject(userInfoUrl, String.class, accessToken, openid);
        log.info(userVoInfo);
        JSONObject userVoObject = JSONObject.parseObject(userVoInfo);
        //用户昵称
        String nickname = userVoObject.getString("nickname");
        //用于昵称是windows1252格式转换为utf-8
        nickname = new String(nickname.getBytes("windows-1256"),"UTF-8");
        log.info("nickname为" + nickname);
        //用户头像
        String headimgurl = jsonObject.getString("headimgurl");
        userInfo = new UserInfo();
        userInfo.setNickName(nickname);
        userInfo.setOpenid(openid);

        //返回name和token字符串
        userInfo.setStatus(1);
        userInfoService.save(userInfo);
    }

    Map<String, Object> map = new HashMap<>();
    String name = userInfo.getName();
    if (StringUtils.isEmpty(name)) {
        name = userInfo.getNickName();
    }
    if (StringUtils.isEmpty(name)) {
        name = userInfo.getPhone();
    }
    map.put("name", name);

    //判断是否有手机号,如果手机号为空,返回openid
    //如果手机号不为空返回openid值为空字符串
    //前端判断,如果openid不为空需要绑定手机号,如果openid为空不需要绑定手机号
    if (StringUtils.isEmpty(userInfo.getPhone())) {
        map.put("openid", userInfo.getOpenid());
    } else {
        map.put("openid", "");
    }

    //使用jwt生成token
    String token = JwtHelper.createToken(userInfo.getId(), name);
    map.put("token", token);
    return "redirect:" + ConstantWxPropertiesUtils.YYGH_BASE_URL + "/weixin/callback?token=" + map.get("token") + "&openid=" + map.get("openid") + "&name=" + URLEncoder.encode((String) map.get("name"), "utf-8");
}

userInfoservice也做了一定的调整

@Override
public UserInfo selectByOpenid(String openid) {
    QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("openid", openid);
    UserInfo userInfo = baseMapper.selectOne(queryWrapper);
    return userInfo;
}

在进行登录接口保存用户时也需要根据openid来判断用户是微信用户还是邮箱用户如果是微信登录那么也是需要绑定微信的.

//绑定手机号
UserInfo userInfo = null;
if (!StringUtils.isEmpty(loginVo.getOpenid())) {
    userInfo = this.selectByOpenid(loginVo.getOpenid());
    if (null != userInfo) {
        userInfo.setPhone(loginVo.getPhone());
        this.updateById(userInfo);
    } else {
        throw new YyghException(ResultCodeEnum.DATA_ERROR);
    }
}

这样就实现了我们的功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6kG3tr4N-1655189829143)(C:\Users\86157\AppData\Local\Temp\1655189775650.png)]

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-16 21:31:54  更:2022-06-16 21:34:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:16:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码