【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【18】认证服务02—微博社交登录


持续学习&持续更新中...

守破离


【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【18】认证服务02---微博社交登录

微博社交登录

OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。

OAuth2.0:对于用户相关的 OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。

Oauth2.0:授权通过后,使用 code 换取 access_token,然后去访问任何开放 API

  • code 用后即毁
  • access_token 在几天内是一样的
  • uid 永久固定

官方版流程

图示原理


前置准备

进入微博开放平台

登陆微博,进入微连接,选择网站接入

创建自己的应用

进入高级信息,填写授权回调页的地址,我们可以在开发阶段进行测试了

添加测试账号(选做)

进入文档,按照流程测试社交登陆:

实现流程

redirect_uri 就是配的 授权回调页
client_id 就是 App Key

在前端引导需要授权的用户到如下地址:

java 复制代码
<li>
    <a href="https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI">
        <img style="width: 50px;height: 18px" src="/static/login/JD_img/weibo.png"/>
    </a>
</li>

如果用户同意授权,页面跳转至 YOUR_REGISTERED_REDIRECT_URI/?code=CODE:在我们的项目里就是:http://auth.gulimall.com/oauth2.0/weibo/success?code=47b9213cf5da2b038ee98fc52f34021d

java 复制代码
    @GetMapping("/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code) throws Exception {}

拿code换取Access Token:https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE

其中client_id=App Key & client_secret=App Secret

java 复制代码
        Map<String, String> headers = new HashMap<>();
        Map<String, String> bodys = new HashMap<>();
        bodys.put("client_id", "3276999101");
        bodys.put("client_secret", "452bbefff4680ac8554b97799a8c12cb");
        bodys.put("grant_type", "authorization_code");
        bodys.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
        bodys.put("code", code);
        //1、根据code换取accessToken;
        HttpResponse response = HttpUtils.doPost(
                "https://api.weibo.com",
                "/oauth2/access_token",
                headers,
                null,
                bodys);

        //2、处理
        if (response.getStatusLine().getStatusCode() == 200) { // 获取到了 accessToken
            String json = EntityUtils.toString(response.getEntity());
            SocialUserAccessToken accessToken = JSON.parseObject(json, SocialUserAccessToken.class);
            String uid = accessToken.getUid();
            // 通过uid就知道当前是哪个社交用户
            //1)、当前用户如果是第一次进网站,进行自动注册(为当前社交用户生成一个会员信息账号,以后这个社交账号就对应指定的会员账号)
            //登录或者注册这个社交用户
            //2)、登录成功就跳回首页
            return "redirect:http://gulimall.com";
        }

拿到Access Token就可以获取用户信息:https://open.weibo.com/apps/3276999101/privilege

比如:根据用户ID获取用户信息:https://open.weibo.com/wiki/2/users/show

java 复制代码
 Map<String,String> query = new HashMap<>();
 query.put("access_token", accessToken);
 query.put("uid",uid);
 HttpResponse response = 
         HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", new HashMap<>(), query);
 if(response.getStatusLine().getStatusCode() == 200){
     //查询成功
     String json = EntityUtils.toString(response.getEntity());
     JSONObject jsonObject = JSON.parseObject(json);
     //获取用户信息
     String name = jsonObject.getString("name");
     String gender = jsonObject.getString("gender");
 }

拿到用户信息就可以判断当前社交用户是否已经登录过系统,快速进行注册/登录。

完整代码

java 复制代码
<a href="https://api.weibo.com/oauth2/authorize?client_id=xxxx&response_type=code&redirect_uri=xxxx">
    <img style="width: 50px;height: 18px" src="/static/login/JD_img/weibo.png"/>
</a>
java 复制代码
    /**
     * 微博用户授权成功回调
     * http://auth.gulimall.com/oauth2.0/weibo/success?code=7d42ee3197927a8807460280d86152cd
     * 拿到code换取Access Token:其中client_id=App Key&client_secret=App Secret
     * POST:https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
     * 拿到Access Token就可以获取用户信息:
     * https://api.weibo.com/2/users/show.json?uid=xxxx&access_token=xxxx
     */

    @GetMapping("/oauth2.0/weibo/success")
    public String weibo(@RequestParam("code") String code) throws Exception {
        Map<String, String> headers = new HashMap<>();
        Map<String, String> bodys = new HashMap<>();
        bodys.put("client_id", "3276999101");
        bodys.put("client_secret", "452bbefff4680ac8554b97799a8c12cb");
        bodys.put("grant_type", "authorization_code");
        bodys.put("redirect_uri", "http://auth.gulimall.com/oauth2.0/weibo/success");
        bodys.put("code", code);
        //1、根据code换取accessToken;
        HttpResponse response = HttpUtils.doPost(
                "https://api.weibo.com",
                "/oauth2/access_token",
                headers,
                null,
                bodys);
        if (response.getStatusLine().getStatusCode() == 200) {
            //2、获取到了 socialUserAccessToken 进行处理
            String json = EntityUtils.toString(response.getEntity());
            SocialUserAccessToken socialUserAccessToken = JSON.parseObject(json, SocialUserAccessToken.class);
//            String uid = socialUserAccessToken.getUid();
            // 通过uid就知道当前是哪个社交用户
            //1)、当前用户如果是第一次进网站,进行自动注册(为当前社交用户生成一个会员信息账号,以后这个社交账号就对应指定的会员账号)
            R r = memberFeignService.socialLogin(socialUserAccessToken);
            if(r.getCode() == BizCodeEnume.SUCCESS.getCode()) {
                //登录或者注册这个社交用户
                //2)、登录成功就跳回首页
                return "redirect:http://gulimall.com";
            }
        }
        return "redirect:http://auth.gulimall.com/login.html";
    }
java 复制代码
    @Override
    public MemberEntity login(SocialUserAccessToken socialUser) {
        //登录和注册合并逻辑

        String uid = socialUser.getUid(); // 社交网站用于标识用户的唯一ID
        String accessToken = socialUser.getAccess_token();

        //1、判断当前社交用户是否已经登录过系统;
        MemberDao memberDao = this.baseMapper;
        MemberEntity memberEntity = memberDao.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));

        long expiresIn = socialUser.getExpires_in();

        if (memberEntity != null) {
            //这个用户已经注册过
            MemberEntity update = new MemberEntity();
            update.setAccessToken(accessToken);
            update.setExpiresIn(expiresIn);
            memberDao.updateById(update);

            memberEntity.setAccessToken(accessToken);
            memberEntity.setExpiresIn(expiresIn);
            return memberEntity;
        } else {
            //2、没有查到当前社交用户对应的记录我们就需要注册一个(将social_id和我们系统的会员id关联起来)
            MemberEntity regist = new MemberEntity();

            try {
                //3、查询当前社交用户的社交账号信息(昵称,性别等)
                Map<String, String> query = new HashMap<>();
                query.put("access_token", accessToken);
                query.put("uid", uid);
                HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json", new HashMap<>(), query);
                if (response.getStatusLine().getStatusCode() == 200) {
                    //查询成功
                    String json = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(json);
                    //获取用户信息
                    String name = jsonObject.getString("name");
                    String gender = jsonObject.getString("gender");
                    //........
                    regist.setNickname(name);
                    regist.setGender("m".equals(gender) ? 1 : 0);
                    //........
                }
            } catch (Exception e) {}

            regist.setSocialUid(socialUser.getUid());
            regist.setAccessToken(accessToken);
            regist.setExpiresIn(expiresIn);

            memberDao.insert(regist);

            return regist;
        }
    }

参考

雷丰阳: Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目.


本文完,感谢您的关注支持!


相关推荐
WX187021128736 小时前
在分布式光伏电站如何进行电能质量的治理?
分布式
掘金-我是哪吒7 小时前
微服务mysql,redis,elasticsearch, kibana,cassandra,mongodb, kafka
redis·mysql·mongodb·elasticsearch·微服务
不能再留遗憾了8 小时前
RabbitMQ 高级特性——消息分发
分布式·rabbitmq·ruby
茶馆大橘8 小时前
微服务系列六:分布式事务与seata
分布式·docker·微服务·nacos·seata·springcloud
58沈剑9 小时前
80后聊架构:架构设计中两个重要指标,延时与吞吐量(Latency vs Throughput) | 架构师之路...
架构
材料苦逼不会梦到计算机白富美11 小时前
golang分布式缓存项目 Day 1
分布式·缓存·golang
想进大厂的小王12 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
Java 第一深情12 小时前
高性能分布式缓存Redis-数据管理与性能提升之道
redis·分布式·缓存
九卷技术录12 小时前
(微服务)服务治理:几种开源限流算法库/应用软件介绍和使用
微服务·服务治理·限流算法
阿伟*rui13 小时前
认识微服务,微服务的拆分,服务治理(nacos注册中心,远程调用)
微服务·架构·firefox