技术经验谈 技术经验谈
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

hss01248

一号线程序员
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 日志体系

  • springboot

  • ruoyi-vue-pro

    • ruoyi-vue-pro-oauth2支持不同客户端同时登录
    • 项目运行备忘
    • flutter项目

    • spring boot内实现流式代理
  • IT工具链
  • java学习路线和视频链接--尚硅谷
  • JDK动态代理原理和应用
  • jvm一图流
  • linux运维
  • spring boot笔记
  • spring-cloud学习资料和路线
  • springcloud alibaba
  • Springcloud学习笔记
  • 从java编译原理到Android aop
  • 大数据
  • 操作系统原理一图流
  • 汇编语言一图流
  • 泛型
  • 网关
  • 面试题精讲
  • java
  • ruoyi-vue-pro
hss01248
2023-05-04

ruoyi-vue-pro-oauth2支持不同客户端同时登录

# ruoyi-vue-pro-oauth2支持不同客户端同时登录

# 背景

默认情况下,ruoyi-vue-pro项目中,web和客户端/pc端无法同时登录,会互踢. 我们期望的效果是能够不同端同时登录,同一个类型的端只能登录一个.

客户端/web端的类型有:

  • Android
  • ios
  • web
  • windows
  • macos

那么如何支持这个特性?

此项目基于oauth2来实现登录和互踢,记录Accesstoken和refreshtoken的system_oauth2_refresh_token表结构为:

image-20230504193122766

看数据,clientId都是"default"

OAuth2中的Client ID通常是一个由服务提供商通过注册创建的唯一标识符,用于标识客户端应用程序或服务。

oauth2里的client的clientId是什么? 一般取值有哪些?

常见的Client ID取值包括:

  1. Web应用程序的域名或URL
  2. 移动应用程序的包名或应用程序ID
  3. 基于设备的应用程序的设备MAC地址或序列号
  4. 帐户级别的访问令牌
  5. 集成其他第三方应用程序时生成的唯一ID。

可以不用增加字段,直接通过改变clientId的值来实现这个功能

那么,改造登录时生成token时入库的clientId,就能实现多端登录功能

# 服务端代码:

    @PostMapping("/refresh-token")
    @Operation(summary = "刷新令牌")
    @Parameter(name = "refreshToken", description = "刷新令牌", required = true)
    @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
    public CommonResult<AppAuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken,HttpServletRequest request) {
        String appName = request.getHeader("appName");
        if(TextUtils.isBlank(appName)){
            appName = OAuth2ClientConstants.appName_default;
        }
        String deviceType = request.getHeader("device-type");
        return success(authService.refreshToken(refreshToken,appName,deviceType));
    }

    // ========== 短信登录相关 ==========

    @PostMapping("/sms-login")
    @Operation(summary = "使用手机 + 验证码登录")
    public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO,HttpServletRequest request) {
        String appName = request.getHeader("appName");
        if(TextUtils.isBlank(appName)){
            appName = OAuth2ClientConstants.appName_default;
        }
        String deviceType = request.getHeader("device-type");
        return success(authService.smsLogin(reqVO,appName,deviceType));
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

service里

cn.iocoder.yudao.module.member.service.auth.MemberAuthServiceImpl

   

private static String getClientId(String appName, String deviceType) {
        String clientId = appName +"-"+ deviceType;
        if("-".equals(clientId)){
            clientId = OAuth2ClientConstants.CLIENT_ID_DEFAULT;
        }
        clientId = clientId.toLowerCase();
        return clientId;
    }

    private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, LoginLogTypeEnum logType,String appName,String deviceType) {
        // 插入登陆日志
        createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS);
        // 创建 Token 令牌
        String clientId = getClientId(appName, deviceType);
        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(user.getId()).setUserType(getUserType().getValue())
                //clientId: 客户端/web端 应用名-端类型
                //.setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
                .setClientId(clientId));
        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenRespDTO);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 两个请求头:

appName: 在nginx代理层加,不同app不同域名加不同的app名字

device-type: flutter侧 dio拦截器加公共请求头

# console配置:

应用管理里新增应用即可

http://localhost:1024/system/oauth2/oauth2/application

image-20230504195910918

编辑 (opens new window)
上次更新: 2023/05/04, 20:09:26
springboo中使用requestParam注解接收jsonBody里的参数
项目运行备忘

← springboo中使用requestParam注解接收jsonBody里的参数 项目运行备忘→

最近更新
01
motion photo的压缩
10-10
02
360全景图的压缩
10-10
03
360全景图的展示
10-10
更多文章>
Theme by Vdoing | Copyright © 2020-2025 | 粤ICP备20041795号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式