This commit is contained in:
parent
c3c02a9473
commit
e3aa1b0fd0
|
@ -53,6 +53,21 @@
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||||
|
<version>1.37.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<!-- 配置冲突,需要排除 -->
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JWT库 -->
|
<!-- JWT库 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.nimbusds</groupId>
|
<groupId>com.nimbusds</groupId>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.recovery.admin.boot.config;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
|
import cn.dev33.satoken.filter.SaServletFilter;
|
||||||
|
import cn.dev33.satoken.same.SaSameUtil;
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sa-Token 权限认证 配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||||
|
// 注册 Sa-Token 全局过滤器
|
||||||
|
@Bean
|
||||||
|
public SaServletFilter getSaServletFilter() {
|
||||||
|
log.info("校验是否是网关转发请求:====================");
|
||||||
|
return new SaServletFilter()
|
||||||
|
.addInclude("/**")
|
||||||
|
.addExclude("/favicon.ico")
|
||||||
|
.setAuth(obj -> {
|
||||||
|
// 校验 Same-Token 身份凭证 —— 以下两句代码可简化为:SaSameUtil.checkCurrentRequestToken();
|
||||||
|
String token = SaHolder.getRequest().getHeader(SaSameUtil.SAME_TOKEN);
|
||||||
|
SaSameUtil.checkToken(token);
|
||||||
|
})
|
||||||
|
.setError(e -> {
|
||||||
|
return SaResult.error(e.getMessage());
|
||||||
|
})
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,15 @@
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||||
|
<version>1.37.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||||
|
@ -46,25 +55,13 @@
|
||||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-oauth2-jose</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.recovery</groupId>
|
<groupId>com.recovery</groupId>
|
||||||
<artifactId>common-web</artifactId>
|
<artifactId>common-web</artifactId>
|
||||||
<version>${hoe-version}</version>
|
<version>${hoe-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- OAuth2 认证服务器-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security.oauth.boot</groupId>
|
|
||||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-oauth2-jose</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
package com.recovery.auth.comm.exception;
|
|
||||||
|
|
||||||
|
|
||||||
import com.recovery.common.base.result.ApiResult;
|
|
||||||
import com.recovery.common.base.result.ResultCode;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.security.authentication.InternalAuthenticationServiceException;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
|
|
||||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
|
||||||
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
|
|
||||||
import org.springframework.security.oauth2.provider.NoSuchClientException;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author:
|
|
||||||
*/
|
|
||||||
@RestControllerAdvice
|
|
||||||
@Slf4j
|
|
||||||
@Order(-1)
|
|
||||||
public class AuthExceptionHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户不存在
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler(UsernameNotFoundException.class)
|
|
||||||
public ApiResult handleUsernameNotFoundException(UsernameNotFoundException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(ResultCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户名和密码异常
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler(InvalidGrantException.class)
|
|
||||||
public ApiResult handleInvalidGrantException(InvalidGrantException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户名和密码异常
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler(InvalidClientException.class)
|
|
||||||
public ApiResult handleInvalidGrantException(InvalidClientException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(ResultCode.CLIENT_AUTHENTICATION_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 账户异常(禁用、锁定、过期)
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler({InternalAuthenticationServiceException.class})
|
|
||||||
public ApiResult handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* token 无效或已过期
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler({InvalidTokenException.class})
|
|
||||||
public ApiResult handleInvalidTokenExceptionException(InvalidTokenException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* token 无效或已过期
|
|
||||||
*
|
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
@ExceptionHandler({NoSuchClientException.class})
|
|
||||||
public ApiResult noSuchClientException(NoSuchClientException e) {
|
|
||||||
log.error("错误信息:{}", e.getMessage(),e);
|
|
||||||
return ApiResult.failed(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
package com.recovery.auth.comm.utils;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
|
|
||||||
import com.recovery.common.base.constant.SecurityConstants;
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author:
|
|
||||||
* @date: 2022/5/23
|
|
||||||
*/
|
|
||||||
public class CommonUtils {
|
|
||||||
public static String getOAuth2ClientId() {
|
|
||||||
|
|
||||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
|
||||||
|
|
||||||
String clientId = request.getParameter(SecurityConstants.CLIENT_ID_KEY);
|
|
||||||
if (StrUtil.isNotBlank(clientId)) {
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
String basic = request.getHeader(SecurityConstants.AUTHORIZATION_KEY);
|
|
||||||
if (StrUtil.isNotBlank(basic) && basic.startsWith(SecurityConstants.BASIC_PREFIX)) {
|
|
||||||
basic = basic.replace(SecurityConstants.BASIC_PREFIX, Strings.EMPTY);
|
|
||||||
String basicPlainText = new String(Base64.getDecoder().decode(basic.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
|
||||||
clientId = basicPlainText.split(":")[0];
|
|
||||||
}
|
|
||||||
return clientId;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,138 +0,0 @@
|
||||||
package com.recovery.auth.config;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
|
||||||
|
|
||||||
import com.recovery.auth.security.details.client.ClientDetailsServiceImpl;
|
|
||||||
import com.recovery.auth.security.details.user.SysUserDetails;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
|
|
||||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
|
||||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
|
||||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
|
|
||||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
|
||||||
import org.springframework.security.oauth2.provider.CompositeTokenGranter;
|
|
||||||
import org.springframework.security.oauth2.provider.TokenGranter;
|
|
||||||
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
|
||||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
|
||||||
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
|
|
||||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
|
||||||
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
|
|
||||||
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created with IntelliJ IDEA.
|
|
||||||
*
|
|
||||||
* @author
|
|
||||||
* @date: 2021/11/24
|
|
||||||
* @description:
|
|
||||||
* @modifiedBy:
|
|
||||||
* @version: 1.0
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
@EnableAuthorizationServer
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
|
|
||||||
|
|
||||||
private final AuthenticationManager authenticationManager;
|
|
||||||
private final ClientDetailsServiceImpl clientDetailsService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OAuth2客户端
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public void configure(ClientDetailsServiceConfigurer clients) {
|
|
||||||
clients.withClientDetails(clientDetailsService);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
|
|
||||||
// Token增强
|
|
||||||
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
|
|
||||||
List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
|
|
||||||
tokenEnhancers.add(tokenEnhancer());
|
|
||||||
tokenEnhancers.add(jwtAccessTokenConverter());
|
|
||||||
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
|
|
||||||
|
|
||||||
// 获取原有默认授权模式(授权码模式、密码模式、客户端模式、简化模式)的授权者
|
|
||||||
List<TokenGranter> granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
|
|
||||||
|
|
||||||
CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
|
|
||||||
endpoints
|
|
||||||
.authenticationManager(authenticationManager)
|
|
||||||
.accessTokenConverter(jwtAccessTokenConverter())
|
|
||||||
.tokenEnhancer(tokenEnhancerChain)
|
|
||||||
.tokenGranter(compositeTokenGranter)
|
|
||||||
.reuseRefreshTokens(true)
|
|
||||||
.tokenServices(tokenServices(endpoints))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
|
|
||||||
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
|
|
||||||
List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
|
|
||||||
tokenEnhancers.add(tokenEnhancer());
|
|
||||||
tokenEnhancers.add(jwtAccessTokenConverter());
|
|
||||||
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
|
|
||||||
|
|
||||||
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
|
||||||
tokenServices.setTokenStore(endpoints.getTokenStore());
|
|
||||||
tokenServices.setSupportRefreshToken(true);
|
|
||||||
tokenServices.setClientDetailsService(clientDetailsService);
|
|
||||||
tokenServices.setTokenEnhancer(tokenEnhancerChain);
|
|
||||||
return tokenServices;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JWT内容增强
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public TokenEnhancer tokenEnhancer() {
|
|
||||||
return (accessToken, authentication) -> {
|
|
||||||
Map<String, Object> additionalInfo = CollectionUtil.newHashMap();
|
|
||||||
Object principal = authentication.getUserAuthentication().getPrincipal();
|
|
||||||
if (principal instanceof SysUserDetails){
|
|
||||||
SysUserDetails sysUserDetails = (SysUserDetails) principal;
|
|
||||||
additionalInfo.put("userId", sysUserDetails.getUserId());
|
|
||||||
additionalInfo.put("username", sysUserDetails.getUsername());
|
|
||||||
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return accessToken;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用非对称加密算法对token签名
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public JwtAccessTokenConverter jwtAccessTokenConverter() {
|
|
||||||
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
|
|
||||||
converter.setKeyPair(keyPair());
|
|
||||||
return converter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密钥库中获取密钥对(公钥+私钥)
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public KeyPair keyPair() {
|
|
||||||
KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "afd123".toCharArray());
|
|
||||||
KeyPair keyPair = factory.getKeyPair("jwt", "afd123".toCharArray());
|
|
||||||
return keyPair;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.recovery.auth.config;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
|
import cn.dev33.satoken.filter.SaServletFilter;
|
||||||
|
import cn.dev33.satoken.same.SaSameUtil;
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sa-Token 权限认证 配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||||
|
// 注册 Sa-Token 全局过滤器
|
||||||
|
@Bean
|
||||||
|
public SaServletFilter getSaServletFilter() {
|
||||||
|
return new SaServletFilter()
|
||||||
|
.addInclude("/**")
|
||||||
|
.addExclude("/favicon.ico")
|
||||||
|
.setAuth(obj -> {
|
||||||
|
// 校验 Same-Token 身份凭证 —— 以下两句代码可简化为:SaSameUtil.checkCurrentRequestToken();
|
||||||
|
String token = SaHolder.getRequest().getHeader(SaSameUtil.SAME_TOKEN);
|
||||||
|
SaSameUtil.checkToken(token);
|
||||||
|
})
|
||||||
|
.setError(e -> {
|
||||||
|
return SaResult.error(e.getMessage());
|
||||||
|
})
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,85 +0,0 @@
|
||||||
package com.recovery.auth.config;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created with IntelliJ IDEA.
|
|
||||||
*
|
|
||||||
* @author:
|
|
||||||
* @date: 2021/11/24
|
|
||||||
* @description:
|
|
||||||
* @modifiedBy:
|
|
||||||
* @version: 1.0
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
private final UserDetailsService sysUserDetailsService;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
|
||||||
http
|
|
||||||
.authorizeRequests().antMatchers("/api/oauth/**").permitAll()
|
|
||||||
.anyRequest().authenticated()
|
|
||||||
.and()
|
|
||||||
.httpBasic()
|
|
||||||
.and()
|
|
||||||
.csrf().disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 认证管理对象
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
|
||||||
return super.authenticationManagerBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加自定义认证器
|
|
||||||
*
|
|
||||||
* @param auth
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
|
||||||
auth.authenticationProvider(daoAuthenticationProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置默认的用户名密码认证授权提供者
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public DaoAuthenticationProvider daoAuthenticationProvider() {
|
|
||||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
|
||||||
provider.setUserDetailsService(sysUserDetailsService);
|
|
||||||
provider.setPasswordEncoder(passwordEncoder());
|
|
||||||
provider.setHideUserNotFoundExceptions(false); // 是否隐藏用户不存在异常,默认:true-隐藏;false-抛出异常;
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +1,25 @@
|
||||||
package com.recovery.auth.controller;
|
package com.recovery.auth.controller;
|
||||||
|
|
||||||
|
|
||||||
import com.nimbusds.jose.jwk.JWKSet;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import com.nimbusds.jose.jwk.RSAKey;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
import com.recovery.auth.exception.BusinessException;
|
||||||
|
import com.recovery.auth.feign.UserFeignClient;
|
||||||
import com.recovery.auth.security.details.user.JwtAuthenticationRequest;
|
import com.recovery.auth.security.details.user.JwtAuthenticationRequest;
|
||||||
import com.recovery.auth.service.AuthService;
|
import com.recovery.auth.service.AuthService;
|
||||||
|
import com.recovery.common.base.dto.UserAuthDTO;
|
||||||
|
import com.recovery.common.base.dto.UserAuthorityDto;
|
||||||
import com.recovery.common.base.result.ApiResult;
|
import com.recovery.common.base.result.ApiResult;
|
||||||
|
import com.recovery.common.base.result.ResultCode;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
|
|
||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author:
|
* @author:
|
||||||
|
@ -32,6 +32,8 @@ public class AuthController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
AuthService authService;
|
AuthService authService;
|
||||||
|
@Resource
|
||||||
|
UserFeignClient userFeignClient;
|
||||||
|
|
||||||
@PostMapping("/token")
|
@PostMapping("/token")
|
||||||
public ApiResult postAccessToken(@RequestBody JwtAuthenticationRequest authenticationRequest, HttpServletRequest request){
|
public ApiResult postAccessToken(@RequestBody JwtAuthenticationRequest authenticationRequest, HttpServletRequest request){
|
||||||
|
@ -46,6 +48,32 @@ public class AuthController {
|
||||||
return ApiResult.ok(map);
|
return ApiResult.ok(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/doLogin")
|
||||||
|
public SaResult doLogin(@RequestBody JwtAuthenticationRequest authenticationRequest) {
|
||||||
|
if(StringUtils.isEmpty(authenticationRequest.getUsername())){
|
||||||
|
throw new BusinessException("账户不能为空");
|
||||||
|
}
|
||||||
|
if(StringUtils.isEmpty(authenticationRequest.getPassword())){
|
||||||
|
throw new BusinessException("密码不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiResult<UserAuthDTO> result = userFeignClient.getUserByUsername(authenticationRequest.getUsername());
|
||||||
|
UserAuthDTO userDetails = new UserAuthDTO();
|
||||||
|
if (ResultCode.SUCCESS.getCode().equals(result.getCode())) {
|
||||||
|
userDetails = result.getData();
|
||||||
|
}
|
||||||
|
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
|
||||||
|
if (userDetails.getUserName().equals(authenticationRequest.getUsername()) && userDetails.getPassword().equals(authenticationRequest.getPassword())) {
|
||||||
|
log.info("密码校验成功!");
|
||||||
|
StpUtil.login(userDetails.getUserName());
|
||||||
|
}else {
|
||||||
|
return SaResult.error("密码错误");
|
||||||
|
}
|
||||||
|
// 第3步,返回给前端
|
||||||
|
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||||
|
return SaResult.ok("登录成功").setData(tokenInfo);
|
||||||
|
}
|
||||||
|
|
||||||
// @GetMapping("/public-key")
|
// @GetMapping("/public-key")
|
||||||
// public Map<String, Object> getPublicKey() {
|
// public Map<String, Object> getPublicKey() {
|
||||||
// //单例模式
|
// //单例模式
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
package com.recovery.auth.security.details.client;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import com.recovery.common.base.enums.PasswordEncoderTypeEnum;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
|
||||||
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
|
||||||
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created with IntelliJ IDEA.
|
|
||||||
*
|
|
||||||
* @author: AI码师
|
|
||||||
* @date: 2021/11/24
|
|
||||||
* @description:
|
|
||||||
* @modifiedBy:
|
|
||||||
* @version: 1.0
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ClientDetailsServiceImpl implements ClientDetailsService {
|
|
||||||
@Override
|
|
||||||
@Cacheable(cacheNames = "auth", key = "'oauth-client:'+#clientId")
|
|
||||||
public ClientDetails loadClientByClientId(String clientId) {
|
|
||||||
// 后面通过feign从管理端获取,目前写死
|
|
||||||
BaseClientDetails clientDetails = new BaseClientDetails(
|
|
||||||
"hoe",
|
|
||||||
"",
|
|
||||||
"all",
|
|
||||||
"password,client_credentials,refresh_token,authorization_code",
|
|
||||||
"",
|
|
||||||
"http://www.baidu.com"
|
|
||||||
|
|
||||||
);
|
|
||||||
clientDetails.setClientSecret(PasswordEncoderTypeEnum.NOOP.getPrefix() + "hoe");
|
|
||||||
clientDetails.setAccessTokenValiditySeconds(3600);
|
|
||||||
clientDetails.setRefreshTokenValiditySeconds(36000000);
|
|
||||||
return clientDetails;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package com.recovery.auth.security.details.user;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public class JwtAuthenticationRequest implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -8445943548965154778L;
|
|
||||||
|
|
||||||
private String username;
|
|
||||||
private String phone;
|
|
||||||
private String password;
|
|
||||||
private String verifyCode;
|
|
||||||
private String loginMethod;
|
|
||||||
private String visitorsType;
|
|
||||||
|
|
||||||
public JwtAuthenticationRequest(String username,String phone,String password,String verifyCode,String loginMethod,String visitorsType) {
|
|
||||||
this.username = username;
|
|
||||||
this.phone = phone;
|
|
||||||
this.password = password;
|
|
||||||
this.verifyCode = verifyCode;
|
|
||||||
this.loginMethod = loginMethod;
|
|
||||||
this.visitorsType = visitorsType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JwtAuthenticationRequest() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserPhone() {
|
|
||||||
return phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUserPhone(String phone) {
|
|
||||||
this.phone = phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVerifyCode() {
|
|
||||||
return verifyCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVerifyCode(String verifyCode) {
|
|
||||||
this.verifyCode = verifyCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLoginMethod() {
|
|
||||||
return loginMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLoginMethod(String loginMethod) {
|
|
||||||
this.loginMethod = loginMethod;
|
|
||||||
}
|
|
||||||
public String getVisitorsType() {
|
|
||||||
return visitorsType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVisitorsType(String visitorsType) {
|
|
||||||
this.visitorsType = visitorsType;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
package com.recovery.auth.security.details.user;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author:
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class SysUserDetails implements UserDetails {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 扩展字段
|
|
||||||
*/
|
|
||||||
private Long userId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认字段
|
|
||||||
*/
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
/**
|
|
||||||
* 是否启用
|
|
||||||
*/
|
|
||||||
private Boolean enabled;
|
|
||||||
/**
|
|
||||||
* 角色
|
|
||||||
*/
|
|
||||||
private Collection<SimpleGrantedAuthority> authorities;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return this.authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPassword() {
|
|
||||||
return this.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return this.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAccountNonExpired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAccountNonLocked() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCredentialsNonExpired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return this.enabled;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package com.recovery.auth.security.details.user;
|
|
||||||
|
|
||||||
import com.recovery.auth.feign.UserFeignClient;
|
|
||||||
import com.recovery.common.base.dto.UserAuthDTO;
|
|
||||||
import com.recovery.common.base.enums.PasswordEncoderTypeEnum;
|
|
||||||
import com.recovery.common.base.result.ApiResult;
|
|
||||||
import com.recovery.common.base.result.ResultCode;
|
|
||||||
import com.recovery.common.base.util.RedisUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.security.authentication.AccountExpiredException;
|
|
||||||
import org.springframework.security.authentication.DisabledException;
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author:
|
|
||||||
*/
|
|
||||||
@Service("sysUserDetailsService")
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class SysUserDetailsServiceImpl implements UserDetailsService {
|
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserFeignClient userFeignClient;
|
|
||||||
@Resource
|
|
||||||
RedisUtil redisUtil;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
|
||||||
// 后面从管理端获取用户信息
|
|
||||||
ApiResult<UserAuthDTO> result = userFeignClient.getUserByUsername(username);
|
|
||||||
SysUserDetails userDetails = null;
|
|
||||||
if (ApiResult.ok().getCode().equals(result.getCode())) {
|
|
||||||
UserAuthDTO user = result.getData();
|
|
||||||
if (null != user) {
|
|
||||||
userDetails = SysUserDetails.builder()
|
|
||||||
.userId(user.getUserId())
|
|
||||||
.username(user.getUserName())
|
|
||||||
//角色
|
|
||||||
// .authorities(handleRoles(user.getRoles()))
|
|
||||||
.enabled(user.getStatus() == 1)
|
|
||||||
.password(PasswordEncoderTypeEnum.BCRYPT.getPrefix() + user.getPassword())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Objects.isNull(userDetails)) {
|
|
||||||
throw new UsernameNotFoundException(ResultCode.USER_NOT_EXIST.getMsg());
|
|
||||||
} else if (!userDetails.isEnabled()) {
|
|
||||||
throw new DisabledException("该账户已被禁用!");
|
|
||||||
} else if (!userDetails.isAccountNonLocked()) {
|
|
||||||
throw new LockedException("该账号已被锁定!");
|
|
||||||
} else if (!userDetails.isAccountNonExpired()) {
|
|
||||||
throw new AccountExpiredException("该账号已过期!");
|
|
||||||
}
|
|
||||||
return userDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<SimpleGrantedAuthority> handleRoles(List<String> roles) {
|
|
||||||
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
|
|
||||||
for (String role : roles) {
|
|
||||||
authorities.add(new SimpleGrantedAuthority(role));
|
|
||||||
}
|
|
||||||
return authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,11 +1,9 @@
|
||||||
package com.recovery.auth.service.impl;
|
package com.recovery.auth.service.impl;
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.recovery.auth.exception.BusinessException;
|
import com.recovery.auth.exception.BusinessException;
|
||||||
import com.recovery.auth.feign.UserFeignClient;
|
import com.recovery.auth.feign.UserFeignClient;
|
||||||
import com.recovery.auth.security.details.user.JwtAuthenticationRequest;
|
import com.recovery.auth.security.details.user.JwtAuthenticationRequest;
|
||||||
import com.recovery.auth.security.details.user.SysUserDetails;
|
|
||||||
import com.recovery.auth.service.AuthService;
|
import com.recovery.auth.service.AuthService;
|
||||||
import com.recovery.common.base.dto.UserAuthDTO;
|
import com.recovery.common.base.dto.UserAuthDTO;
|
||||||
import com.recovery.common.base.dto.UserAuthorityDto;
|
import com.recovery.common.base.dto.UserAuthorityDto;
|
||||||
|
@ -15,16 +13,11 @@ import com.recovery.common.base.util.EncryptUtil;
|
||||||
import com.recovery.common.base.util.RedisUtil;
|
import com.recovery.common.base.util.RedisUtil;
|
||||||
import com.recovery.common.base.utils.JwtUtils;
|
import com.recovery.common.base.utils.JwtUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.authentication.AccountExpiredException;
|
|
||||||
import org.springframework.security.authentication.DisabledException;
|
|
||||||
import org.springframework.security.authentication.LockedException;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,6 +48,22 @@
|
||||||
<artifactId>spring-jdbc</artifactId>
|
<artifactId>spring-jdbc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- httpClient依赖,缺少此依赖api网关转发请求时可能发生503错误 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.13</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
|
||||||
|
<version>1.34.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- MySQL 连接驱动依赖 -->
|
<!-- MySQL 连接驱动依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.recovery.gateway.config;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
|
||||||
|
import cn.dev33.satoken.router.SaRouter;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Sa-Token 权限认证] 配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SaTokenConfigure {
|
||||||
|
// 注册 Sa-Token全局过滤器
|
||||||
|
@Bean
|
||||||
|
public SaReactorFilter getSaReactorFilter() {
|
||||||
|
return new SaReactorFilter()
|
||||||
|
// 拦截地址
|
||||||
|
.addInclude("/**") /* 拦截全部path */
|
||||||
|
// 开放地址
|
||||||
|
.addExclude("/favicon.ico")
|
||||||
|
// 鉴权方法:每次访问进入
|
||||||
|
.setAuth(obj -> {
|
||||||
|
// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
|
||||||
|
SaRouter.match("/**", "/auth/oauth/doLogin", r -> StpUtil.checkLogin());
|
||||||
|
|
||||||
|
// 权限认证 -- 不同模块, 校验不同权限
|
||||||
|
SaRouter.match("/api/test1", r -> StpUtil.checkPermission("api.test1"));
|
||||||
|
SaRouter.match("/api/test2", r -> StpUtil.checkPermission("api.test2"));
|
||||||
|
SaRouter.match("/api/test3", r -> StpUtil.checkRoleOr("admin", "super"));
|
||||||
|
|
||||||
|
// 更多匹配 ... */
|
||||||
|
})
|
||||||
|
// 异常处理方法:每次setAuth函数出现异常时进入
|
||||||
|
.setError(e -> {
|
||||||
|
return SaResult.error(e.getMessage());
|
||||||
|
})
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,80 +1,80 @@
|
||||||
package com.recovery.gateway.security;
|
//package com.recovery.gateway.security;
|
||||||
|
//
|
||||||
|
//
|
||||||
import com.recovery.common.base.constant.SecurityConstants;
|
//import com.recovery.common.base.constant.SecurityConstants;
|
||||||
import com.recovery.common.base.result.ResultCode;
|
//import com.recovery.common.base.result.ResultCode;
|
||||||
import com.recovery.gateway.util.ResponseUtils;
|
//import com.recovery.gateway.util.ResponseUtils;
|
||||||
import lombok.AllArgsConstructor;
|
//import lombok.AllArgsConstructor;
|
||||||
import org.springframework.context.annotation.Bean;
|
//import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
//import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
//import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
//import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
//import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
//import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||||
import org.springframework.security.oauth2.jwt.Jwt;
|
//import org.springframework.security.oauth2.jwt.Jwt;
|
||||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
//import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
//import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||||
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
|
//import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
//import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
//import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
//import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||||
import reactor.core.publisher.Mono;
|
//import reactor.core.publisher.Mono;
|
||||||
/**
|
///**
|
||||||
* @author:
|
// * @author:
|
||||||
*/
|
// */
|
||||||
@AllArgsConstructor
|
//@AllArgsConstructor
|
||||||
@Configuration
|
//@Configuration
|
||||||
@EnableWebFluxSecurity
|
//@EnableWebFluxSecurity
|
||||||
public class ResourceServerConfig {
|
//public class ResourceServerConfig {
|
||||||
|
//
|
||||||
private final ResourceServerManager resourceServerManager;
|
// private final ResourceServerManager resourceServerManager;
|
||||||
|
//
|
||||||
@Bean
|
// @Bean
|
||||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
// public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||||
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
|
// http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
|
||||||
http.oauth2ResourceServer().authenticationEntryPoint(authenticationEntryPoint());
|
// http.oauth2ResourceServer().authenticationEntryPoint(authenticationEntryPoint());
|
||||||
http.authorizeExchange()
|
// http.authorizeExchange()
|
||||||
.anyExchange().access(resourceServerManager)
|
// .anyExchange().access(resourceServerManager)
|
||||||
.and()
|
// .and()
|
||||||
.exceptionHandling()
|
// .exceptionHandling()
|
||||||
.accessDeniedHandler(accessDeniedHandler()) // 处理未授权
|
// .accessDeniedHandler(accessDeniedHandler()) // 处理未授权
|
||||||
.authenticationEntryPoint(authenticationEntryPoint()) //处理未认证
|
// .authenticationEntryPoint(authenticationEntryPoint()) //处理未认证
|
||||||
.and().csrf().disable();
|
// .and().csrf().disable();
|
||||||
return http.build();
|
// return http.build();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 自定义未授权响应
|
// * 自定义未授权响应
|
||||||
*/
|
// */
|
||||||
@Bean
|
// @Bean
|
||||||
ServerAccessDeniedHandler accessDeniedHandler() {
|
// ServerAccessDeniedHandler accessDeniedHandler() {
|
||||||
return (exchange, denied) -> {
|
// return (exchange, denied) -> {
|
||||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
// Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
||||||
.flatMap(response -> ResponseUtils.writeErrorInfo(response, ResultCode.ACCESS_UNAUTHORIZED));
|
// .flatMap(response -> ResponseUtils.writeErrorInfo(response, ResultCode.ACCESS_UNAUTHORIZED));
|
||||||
return mono;
|
// return mono;
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* token无效或者已过期自定义响应
|
// * token无效或者已过期自定义响应
|
||||||
*/
|
// */
|
||||||
@Bean
|
// @Bean
|
||||||
ServerAuthenticationEntryPoint authenticationEntryPoint() {
|
// ServerAuthenticationEntryPoint authenticationEntryPoint() {
|
||||||
return (exchange, e) -> {
|
// return (exchange, e) -> {
|
||||||
Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
// Mono<Void> mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
|
||||||
.flatMap(response -> ResponseUtils.writeErrorInfo(response, ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
// .flatMap(response -> ResponseUtils.writeErrorInfo(response, ResultCode.TOKEN_INVALID_OR_EXPIRED));
|
||||||
return mono;
|
// return mono;
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Bean
|
// @Bean
|
||||||
public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
|
// public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
|
||||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
// JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||||
jwtGrantedAuthoritiesConverter.setAuthorityPrefix(SecurityConstants.AUTHORITY_PREFIX);
|
// jwtGrantedAuthoritiesConverter.setAuthorityPrefix(SecurityConstants.AUTHORITY_PREFIX);
|
||||||
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(SecurityConstants.JWT_AUTHORITIES_KEY);
|
// jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(SecurityConstants.JWT_AUTHORITIES_KEY);
|
||||||
|
//
|
||||||
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
// JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
|
// jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
|
||||||
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
|
// return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
|
@ -1,122 +1,79 @@
|
||||||
package com.recovery.gateway.security;
|
//package com.recovery.gateway.security;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
|
|
||||||
import com.recovery.common.base.constant.GlobalConstants;
|
|
||||||
import com.recovery.common.base.constant.SecurityConstants;
|
|
||||||
import com.recovery.gateway.util.UrlPatternUtils;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
|
||||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.web.server.authorization.AuthorizationContext;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.AntPathMatcher;
|
|
||||||
import org.springframework.util.PathMatcher;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
/**
|
|
||||||
* Created with IntelliJ IDEA.
|
|
||||||
*
|
|
||||||
* @author: AI码师 关注公众号"AI码师"获取完整源码
|
|
||||||
* @date: 2021/11/24
|
|
||||||
* @description:
|
|
||||||
* @modifiedBy:
|
|
||||||
* @version: 1.0
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Slf4j
|
|
||||||
@ConfigurationProperties(prefix = "security")
|
|
||||||
public class ResourceServerManager implements ReactiveAuthorizationManager<AuthorizationContext> {
|
|
||||||
private final RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
private List<String> ignoreUrls;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
|
|
||||||
ServerHttpRequest request = authorizationContext.getExchange().getRequest();
|
|
||||||
if (request.getMethod() == HttpMethod.OPTIONS) { // 预检请求放行
|
|
||||||
return Mono.just(new AuthorizationDecision(true));
|
|
||||||
}
|
|
||||||
PathMatcher pathMatcher = new AntPathMatcher();
|
|
||||||
String method = request.getMethodValue();
|
|
||||||
String path = request.getURI().getPath();
|
|
||||||
|
|
||||||
// 跳过token校验,放在这里去做是为了能够动态刷新
|
|
||||||
// if (skipValid(path)) {
|
|
||||||
return Mono.just(new AuthorizationDecision(true));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 如果token为空 或者token不合法 则进行拦截
|
|
||||||
// String restfulPath = method + ":" + path; // RESTFul接口权限设计 @link https://www.cnblogs.com/haoxianrui/p/14961707.html
|
|
||||||
// String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_KEY);
|
|
||||||
// if (StrUtil.isBlank(token) || !StrUtil.startWithIgnoreCase(token, SecurityConstants.JWT_PREFIX)) {
|
|
||||||
// return Mono.just(new AuthorizationDecision(false));
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// // 从redis中获取资源权限
|
//import cn.hutool.core.collection.CollectionUtil;
|
||||||
// Map<String, Object> urlPermRolesRules = redisTemplate.opsForHash().entries(GlobalConstants.URL_PERM_ROLES_KEY);
|
//import cn.hutool.core.convert.Convert;
|
||||||
// List<String> authorizedRoles = new ArrayList<>(); // 拥有访问权限的角色
|
//import cn.hutool.core.util.StrUtil;
|
||||||
// boolean requireCheck = false; // 是否需要鉴权,默认未设置拦截规则不需鉴权
|
|
||||||
//
|
//
|
||||||
// // 获取当前资源 所需要的角色
|
//import com.recovery.common.base.constant.GlobalConstants;
|
||||||
// for (Map.Entry<String, Object> permRoles : urlPermRolesRules.entrySet()) {
|
//import com.recovery.common.base.constant.SecurityConstants;
|
||||||
// String perm = permRoles.getKey();
|
//import com.recovery.gateway.util.UrlPatternUtils;
|
||||||
// if (pathMatcher.match(perm, restfulPath)) {
|
//import lombok.RequiredArgsConstructor;
|
||||||
// List<String> roles = Convert.toList(String.class, permRoles.getValue());
|
//import lombok.Setter;
|
||||||
// authorizedRoles.addAll(Convert.toList(String.class, roles));
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
// if (requireCheck == false) {
|
//import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
// requireCheck = true;
|
//import org.springframework.data.redis.core.RedisTemplate;
|
||||||
// }
|
//import org.springframework.http.HttpMethod;
|
||||||
// }
|
//import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
// }
|
//import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
|
//import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||||
|
//import org.springframework.security.core.Authentication;
|
||||||
|
//import org.springframework.security.core.GrantedAuthority;
|
||||||
|
//import org.springframework.security.web.server.authorization.AuthorizationContext;
|
||||||
|
//import org.springframework.stereotype.Component;
|
||||||
|
//import org.springframework.util.AntPathMatcher;
|
||||||
|
//import org.springframework.util.PathMatcher;
|
||||||
|
//import reactor.core.publisher.Mono;
|
||||||
//
|
//
|
||||||
// // 如果资源不需要权限 则直接返回授权成功
|
//import java.util.ArrayList;
|
||||||
// if (!requireCheck) {
|
//import java.util.List;
|
||||||
|
//import java.util.Map;
|
||||||
|
///**
|
||||||
|
// * Created with IntelliJ IDEA.
|
||||||
|
// *
|
||||||
|
// * @author:
|
||||||
|
// * @date: 2021/11/24
|
||||||
|
// * @description:
|
||||||
|
// * @modifiedBy:
|
||||||
|
// * @version: 1.0
|
||||||
|
// */
|
||||||
|
//@Component
|
||||||
|
//@RequiredArgsConstructor
|
||||||
|
//@Slf4j
|
||||||
|
//@ConfigurationProperties(prefix = "security")
|
||||||
|
//public class ResourceServerManager implements ReactiveAuthorizationManager<AuthorizationContext> {
|
||||||
|
// private final RedisTemplate redisTemplate;
|
||||||
|
//
|
||||||
|
// @Setter
|
||||||
|
// private List<String> ignoreUrls;
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
|
||||||
|
// ServerHttpRequest request = authorizationContext.getExchange().getRequest();
|
||||||
|
// if (request.getMethod() == HttpMethod.OPTIONS) { // 预检请求放行
|
||||||
// return Mono.just(new AuthorizationDecision(true));
|
// return Mono.just(new AuthorizationDecision(true));
|
||||||
// }
|
// }
|
||||||
|
// PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
|
// String method = request.getMethodValue();
|
||||||
|
// String path = request.getURI().getPath();
|
||||||
//
|
//
|
||||||
// // 判断JWT中携带的用户角色是否有权限访问
|
// // 跳过token校验,放在这里去做是为了能够动态刷新
|
||||||
// Mono<AuthorizationDecision> authorizationDecisionMono = mono
|
//// if (skipValid(path)) {
|
||||||
// .filter(Authentication::isAuthenticated)
|
// return Mono.just(new AuthorizationDecision(true));
|
||||||
// .flatMapIterable(Authentication::getAuthorities)
|
//// }
|
||||||
// .map(GrantedAuthority::getAuthority)
|
// }
|
||||||
// .any(authority -> {
|
//
|
||||||
// String roleCode = authority.substring(SecurityConstants.AUTHORITY_PREFIX.length()); // 用户的角色
|
// /**
|
||||||
// boolean hasAuthorized = CollectionUtil.isNotEmpty(authorizedRoles) && authorizedRoles.contains(roleCode);
|
// * 跳过校验
|
||||||
// return hasAuthorized;
|
// *
|
||||||
// })
|
// * @param path
|
||||||
// .map(AuthorizationDecision::new)
|
// * @return
|
||||||
// .defaultIfEmpty(new AuthorizationDecision(false));
|
// */
|
||||||
// return authorizationDecisionMono;
|
// private boolean skipValid(String path) {
|
||||||
}
|
// for (String skipPath : ignoreUrls) {
|
||||||
|
// if (UrlPatternUtils.match(skipPath, path)) {
|
||||||
/**
|
// return true;
|
||||||
* 跳过校验
|
// }
|
||||||
*
|
// }
|
||||||
* @param path
|
// return false;
|
||||||
* @return
|
// }
|
||||||
*/
|
//}
|
||||||
private boolean skipValid(String path) {
|
|
||||||
for (String skipPath : ignoreUrls) {
|
|
||||||
if (UrlPatternUtils.match(skipPath, path)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +1,69 @@
|
||||||
package com.recovery.gateway.security;
|
//package com.recovery.gateway.security;
|
||||||
|
//
|
||||||
import cn.hutool.core.util.StrUtil;
|
//import cn.dev33.satoken.same.SaSameUtil;
|
||||||
|
//import cn.hutool.core.util.StrUtil;
|
||||||
import com.nimbusds.jose.JWSObject;
|
//
|
||||||
import com.recovery.common.base.constant.SecurityConstants;
|
//import com.nimbusds.jose.JWSObject;
|
||||||
import lombok.RequiredArgsConstructor;
|
//import com.recovery.common.base.constant.SecurityConstants;
|
||||||
import lombok.SneakyThrows;
|
//import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
//import lombok.SneakyThrows;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
//import org.apache.logging.log4j.util.Strings;
|
||||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
import org.springframework.core.Ordered;
|
//import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
//import org.springframework.core.Ordered;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
//import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
//import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.stereotype.Component;
|
//import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
//import org.springframework.stereotype.Component;
|
||||||
import reactor.core.publisher.Mono;
|
//import org.springframework.web.server.ServerWebExchange;
|
||||||
|
//import reactor.core.publisher.Mono;
|
||||||
import java.net.URLEncoder;
|
//
|
||||||
/**
|
//import java.net.URLEncoder;
|
||||||
* Created with IntelliJ IDEA.
|
///**
|
||||||
*
|
// * Created with IntelliJ IDEA.
|
||||||
* @author: AI码师 关注公众号"AI码师"获取完整源码
|
// *
|
||||||
* @date: 2021/11/24
|
// * @author: AI码师 关注公众号"AI码师"获取完整源码
|
||||||
* @description:
|
// * @date: 2021/11/24
|
||||||
* @modifiedBy:
|
// * @description:
|
||||||
* @version: 1.0
|
// * @modifiedBy:
|
||||||
*/
|
// * @version: 1.0
|
||||||
@Component
|
// */
|
||||||
@Slf4j
|
//@Component
|
||||||
@RequiredArgsConstructor
|
//@Slf4j
|
||||||
public class SecurityGlobalFilter implements GlobalFilter, Ordered {
|
//@RequiredArgsConstructor
|
||||||
|
//public class SecurityGlobalFilter implements GlobalFilter, Ordered {
|
||||||
@SneakyThrows
|
//
|
||||||
@Override
|
// @SneakyThrows
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
// @Override
|
||||||
|
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
ServerHttpRequest request = exchange.getRequest();
|
//
|
||||||
log.info("接受到请求地址:"+request.getURI());
|
// ServerHttpRequest request = exchange.getRequest();
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
// log.info("接受到请求地址:"+request.getURI());
|
||||||
// 不是正确的的JWT不做解析处理
|
// ServerHttpResponse response = exchange.getResponse();
|
||||||
String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_KEY);
|
// // 不是正确的的JWT不做解析处理
|
||||||
if (StrUtil.isBlank(token) || !StrUtil.startWithIgnoreCase(token, SecurityConstants.JWT_PREFIX)) {
|
// String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_KEY);
|
||||||
return chain.filter(exchange);
|
// if (StrUtil.isBlank(token) || !StrUtil.startWithIgnoreCase(token, SecurityConstants.JWT_PREFIX)) {
|
||||||
}
|
// return chain.filter(exchange);
|
||||||
// 解析JWT获取jti,以jti为key判断redis的黑名单列表是否存在,存在则拦截访问
|
// }
|
||||||
token = StrUtil.replaceIgnoreCase(token, SecurityConstants.JWT_PREFIX, Strings.EMPTY);
|
// // 为请求追加 Same-Token 参数
|
||||||
String payload = StrUtil.toString(JWSObject.parse(token).getPayload());
|
// request.mutate()
|
||||||
request = exchange.getRequest().mutate()
|
// // 为请求追加 Same-Token 参数
|
||||||
.header(SecurityConstants.JWT_PAYLOAD_KEY, URLEncoder.encode(payload, "UTF-8"))
|
// .header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken())
|
||||||
.build();
|
// .build();
|
||||||
exchange = exchange.mutate().request(request).build();
|
// //结束
|
||||||
return chain.filter(exchange);
|
// // 解析JWT获取jti,以jti为key判断redis的黑名单列表是否存在,存在则拦截访问
|
||||||
}
|
// token = StrUtil.replaceIgnoreCase(token, SecurityConstants.JWT_PREFIX, Strings.EMPTY);
|
||||||
|
// String payload = StrUtil.toString(JWSObject.parse(token).getPayload());
|
||||||
@Override
|
// request = exchange.getRequest().mutate()
|
||||||
public int getOrder() {
|
// .header(SecurityConstants.JWT_PAYLOAD_KEY, URLEncoder.encode(payload, "UTF-8"))
|
||||||
return 0;
|
// .build();
|
||||||
}
|
// exchange = exchange.mutate().request(request).build();
|
||||||
}
|
// return chain.filter(exchange);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public int getOrder() {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
//}
|
10
pom.xml
10
pom.xml
|
@ -46,6 +46,16 @@
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>${hutool-version}</version>
|
<version>${hutool-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-redis-jackson</artifactId>
|
||||||
|
<version>1.37.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<!-- end -->
|
<!-- end -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
Loading…
Reference in New Issue