【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【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架构师 | 微服务 | 大型电商项目.


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


相关推荐
葫芦的运维日志1 小时前
从手动部署到GitOps只需四步
架构
sumuve2 小时前
从100行到1行:我是如何重构IoT设备实时数据通信的?
架构·响应式设计
koddnty2 小时前
c++协程控制流深入剖析
后端·架构
Mintopia3 小时前
Vite 与 Uni-App X 的协作原理:从前端开发到多端运行的桥梁
架构
louiX19 小时前
深入理解 Android BLE GATT 回调机制:从“回调地狱”到高可靠 OTA 架构
架构
aircrushin19 小时前
轻量化大模型架构演进
人工智能·架构
天蓝色的鱼鱼19 小时前
你的项目真的需要SSR吗?还是只是你的简历需要?
前端·架构
文心快码BaiduComate20 小时前
百度云与光本位签署战略合作:用AI Agent 重构芯片研发流程
前端·人工智能·架构
JavaTalks1 天前
高并发保护实战:限流、熔断、降级如何配合落地
后端·架构·设计
stark张宇1 天前
微服务架构必备:Gin + gRPC + Consul + Nacos + GORM 打造用户服务
微服务·gin·grpc