security: query string 支持传递 token 参数,解决 ws token 认证
This commit is contained in:
parent
41c324acc3
commit
6a61db8508
|
@ -19,6 +19,13 @@ public class SecurityProperties {
|
|||
*/
|
||||
@NotEmpty(message = "Token Header 不能为空")
|
||||
private String tokenHeader = "Authorization";
|
||||
/**
|
||||
* HTTP 请求时,访问令牌的请求参数
|
||||
*
|
||||
* 初始目的:解决 WebSocket 无法通过 header 传参,只能通过 token 参数拼接
|
||||
*/
|
||||
@NotEmpty(message = "Token Parameter 不能为空")
|
||||
private String tokenParameter = "token";
|
||||
|
||||
/**
|
||||
* mock 模式的开关
|
||||
|
|
|
@ -129,8 +129,6 @@ public class YudaoWebSecurityConfigurerAdapter {
|
|||
.antMatchers(buildAppApi("/**")).permitAll()
|
||||
// 1.5 验证码captcha 允许匿名访问
|
||||
.antMatchers("/captcha/get", "/captcha/check").permitAll()
|
||||
// 1.6 webSocket 允许匿名访问
|
||||
.antMatchers("/websocket/message").permitAll()
|
||||
// ②:每个项目的自定义规则
|
||||
.and().authorizeRequests(registry -> // 下面,循环设置自定义规则
|
||||
authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
|
||||
|
|
|
@ -41,7 +41,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
|||
@SuppressWarnings("NullableProblems")
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request,
|
||||
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
|
||||
if (StrUtil.isNotEmpty(token)) {
|
||||
Integer userType = WebFrameworkUtils.getLoginUserType(request);
|
||||
try {
|
||||
|
@ -74,7 +75,10 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
|||
return null;
|
||||
}
|
||||
// 用户类型不匹配,无权限
|
||||
if (ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
|
||||
// 注意:只有 /admin-api/* 和 /app-api/* 有 userType,才需要比对用户类型
|
||||
// TODO 芋艿:ws 要不要区分开?
|
||||
if (userType != null
|
||||
&& ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
|
||||
throw new AccessDeniedException("错误的用户类型");
|
||||
}
|
||||
// 构建登录用户
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.framework.security.core.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
@ -20,6 +21,9 @@ import java.util.Collections;
|
|||
*/
|
||||
public class SecurityFrameworkUtils {
|
||||
|
||||
/**
|
||||
* HEADER 认证头 value 的前缀
|
||||
*/
|
||||
public static final String AUTHORIZATION_BEARER = "Bearer";
|
||||
|
||||
private SecurityFrameworkUtils() {}
|
||||
|
@ -28,19 +32,23 @@ public class SecurityFrameworkUtils {
|
|||
* 从请求中,获得认证 Token
|
||||
*
|
||||
* @param request 请求
|
||||
* @param header 认证 Token 对应的 Header 名字
|
||||
* @param headerName 认证 Token 对应的 Header 名字
|
||||
* @param parameterName 认证 Token 对应的 Parameter 名字
|
||||
* @return 认证 Token
|
||||
*/
|
||||
public static String obtainAuthorization(HttpServletRequest request, String header) {
|
||||
String authorization = request.getHeader(header);
|
||||
if (!StringUtils.hasText(authorization)) {
|
||||
public static String obtainAuthorization(HttpServletRequest request,
|
||||
String headerName, String parameterName) {
|
||||
// 1. 获得 Token。优先级:Header > Parameter
|
||||
String token = request.getHeader(headerName);
|
||||
if (StrUtil.isEmpty(token)) {
|
||||
token = request.getParameter(parameterName);
|
||||
}
|
||||
if (!StringUtils.hasText(token)) {
|
||||
return null;
|
||||
}
|
||||
int index = authorization.indexOf(AUTHORIZATION_BEARER + " ");
|
||||
if (index == -1) { // 未找到
|
||||
return null;
|
||||
}
|
||||
return authorization.substring(index + 7).trim();
|
||||
// 2. 去除 Token 中带的 Bearer
|
||||
int index = token.indexOf(AUTHORIZATION_BEARER + " ");
|
||||
return index >= 0 ? token.substring(index + 7).trim() : token;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,7 +53,8 @@ public class AppAuthController {
|
|||
@PermitAll
|
||||
@Operation(summary = "登出系统")
|
||||
public CommonResult<Boolean> logout(HttpServletRequest request) {
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request,
|
||||
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
authService.logout(token);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
|||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||
|
@ -38,7 +39,6 @@ import java.util.Set;
|
|||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.obtainAuthorization;
|
||||
|
||||
@Tag(name = "管理后台 - 认证")
|
||||
@RestController
|
||||
|
@ -76,7 +76,8 @@ public class AuthController {
|
|||
@Operation(summary = "登出系统")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<Boolean> logout(HttpServletRequest request) {
|
||||
String token = obtainAuthorization(request, securityProperties.getTokenHeader());
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request,
|
||||
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue