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


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


相关推荐
喜欢的名字被抢了17 分钟前
从零构建-AI-侧边栏(一)-架构-流式对话与模型管理
chrome·架构·浏览器扩展
ACP广源盛139246256731 小时前
国产算力互联IX8024@ACP#Kimi K3 开源后的端侧部署硬件架构分析
大数据·人工智能·分布式·单片机·嵌入式硬件
l1t2 小时前
DeepSeek总结的DuckLake 架构深度剖析-1
数据库·架构
花生了什么事o2 小时前
分布式 ID 生成方案:从数据库自增到雪花算法
数据库·分布式·算法
极客BIM工作室2 小时前
从OCCT STEP读写架构,看懂格式数据转换的底层设计逻辑
架构
AINative软件工程3 小时前
MCP Server 权限边界工程实践:OAuth、最小权限与工具沙箱,别让 Agent 拿到整台机器
架构·llm·ai编程
微三云 - 廖会灵 (私域系统开发)3 小时前
企业级系统开发避坑指南:源码交付与高并发架构,我们为什么最终选了微三云
架构
程序员小羊!12 小时前
集团多事业部架构下数仓分层建模规范
架构
ARM|X86+FPGA工业主板厂家13 小时前
RK3588+FPGA+EtherCAT异构架构解析|工业场景如何同时保住AI算力与微秒级运动实时性
人工智能·fpga开发·架构
小码哥哥14 小时前
四大企业AI知识库技术架构深度对比:从设计哲学到实现差异
人工智能·架构