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