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表结构为:

看数据,clientId都是"default"
OAuth2中的Client ID通常是一个由服务提供商通过注册创建的唯一标识符,用于标识客户端应用程序或服务。
oauth2里的client的clientId是什么? 一般取值有哪些?
常见的Client ID取值包括:
- Web应用程序的域名或URL
- 移动应用程序的包名或应用程序ID
- 基于设备的应用程序的设备MAC地址或序列号
- 帐户级别的访问令牌
- 集成其他第三方应用程序时生成的唯一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
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
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

编辑 (opens new window)
上次更新: 2023/05/04, 20:09:26