本文最后更新于129 天前,其中的信息可能已经过时,如有错误请发送邮件到3088506834@qq.com
过滤链配置
配置关闭csrf并关闭默认登录接口,且从 application.yml 获取排除url规则进行排除
@Resource
private SecurityExcludedUrlsConfig excludedUrlsConfig;
@Bean
public SecurityFilterChain customSecurityFilterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class)
.userDetailsService(customerUserDetailsService)
.formLogin(AbstractHttpConfigurer::disable
)
.csrf(csrf -> csrf.disable())
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authorizeHttpRequests(auth -> {
excludedUrlsConfig.getUrls().forEach(url -> auth.requestMatchers(url).permitAll());
auth.anyRequest().authenticated();
})
.exceptionHandling(exceptionHandling ->
exceptionHandling
.authenticationEntryPoint(loginAuthenticationHandler)
.accessDeniedHandler(loginAccessDefineHandler)
)
.cors(cors -> cors.configurationSource(configurationSource()))
.headers(headers -> headers.frameOptions(frameOptionsConfig -> frameOptionsConfig.disable()))
.headers(headers -> headers.frameOptions(frameOptionsConfig -> frameOptionsConfig.sameOrigin()));
return http.build();
}JavaSecurityExcludedUrlsConfig.class
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* online.yudream.platform.config
*
* @author SiberianHusky
* * @date 2025/7/5
*/
@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix = "security.excluded-urls")
public class SecurityExcludedUrlsConfig {
private List<String> urls;
}Javaapplication.yml
security:
excluded-urls:
urls:
- /user/login
- /user/registerJava跨域配置
private CorsConfigurationSource configurationSource() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
corsConfiguration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}JavaSecurityConfig.class
package online.yudream.platform.config;
import jakarta.annotation.Resource;
import online.yudream.platform.filter.CheckTokenFilter;
import online.yudream.platform.handler.AjaxAuthenticationFailureHandler;
import online.yudream.platform.handler.AjaxAuthenticationSuccessHandler;
import online.yudream.platform.handler.LoginAccessDefineHandler;
import online.yudream.platform.handler.LoginAuthenticationHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Collections;
@Configuration
@EnableWebSecurity()
@EnableMethodSecurity
public class SecurityConfig implements WebSecurityConfigurer<WebSecurity> {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;
// @Autowired
// private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;
@Resource
private LoginAuthenticationHandler loginAuthenticationHandler;
@Resource
private LoginAccessDefineHandler loginAccessDefineHandler;
@Resource
private CheckTokenFilter checkTokenFilter;
@Resource
private UserDetailsService customerUserDetailsService;
@Resource
private SecurityExcludedUrlsConfig excludedUrlsConfig;
@Bean
public SecurityFilterChain customSecurityFilterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class)
.userDetailsService(customerUserDetailsService)
.formLogin(AbstractHttpConfigurer::disable
)
.csrf(csrf -> csrf.disable())
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authorizeHttpRequests(auth -> {
excludedUrlsConfig.getUrls().forEach(url -> auth.requestMatchers(url).permitAll());
auth.anyRequest().authenticated();
})
.exceptionHandling(exceptionHandling ->
exceptionHandling
.authenticationEntryPoint(loginAuthenticationHandler)
.accessDeniedHandler(loginAccessDefineHandler)
)
.cors(cors -> cors.configurationSource(configurationSource()))
.headers(headers -> headers.frameOptions(frameOptionsConfig -> frameOptionsConfig.disable()))
.headers(headers -> headers.frameOptions(frameOptionsConfig -> frameOptionsConfig.sameOrigin()));
return http.build();
}
private CorsConfigurationSource configurationSource() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
corsConfiguration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Override
public void init(WebSecurity builder) throws Exception {
}
@Override
public void configure(WebSecurity builder) throws Exception {
}
}JavaJWT过滤层
JwtUtils
package online.yudream.platform.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import online.yudream.platform.exception.CustomerAuthenticationException;
import org.apache.tomcat.websocket.AuthenticationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Map;
/**
* online.yudream.platform.utils
*
* @author SiberianHusky
* * @date 2025/7/5
*/
@Component
public class JWTUtils {
@Value("${application.security.jwt.secret-key}")
private String SECRET;
@Value("${application.security.jwt.expiration}")
private int EXPIRATION;
@Value("${application.security.jwt.refresh-token.expiration}")
private int REFRESH_TOKEN_EXPIRATION;
/**
* @Param: 传入需要设置的payload信息
* @return: 返回token
*/
public String generateToken(Map<String, String> map) {
return getJwt(map, EXPIRATION);
}
public String getJwt(Map<String, String> map, int refreshTokenExpiration) {
JWTCreator.Builder builder = JWT.create();
map.forEach(builder::withClaim);
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, refreshTokenExpiration);
builder.withExpiresAt(instance.getTime());
return builder.sign(Algorithm.HMAC256(SECRET));
}
/**
* @Param: 传入token
* @return:
*/
public void verify(String token) {
try {
JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
} catch (Exception e) {
throw new CustomerAuthenticationException("token验证失败");
}
}
/**
* @Param: 传入token
* @return: 解密的token信息
*/
public String getTokenInfo(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token).getClaim("username").asString();
}
}
JavaCheckTokenFilter
package online.yudream.platform.filter;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import online.yudream.platform.config.SecurityExcludedUrlsConfig;
import online.yudream.platform.exception.CustomerAuthenticationException;
import online.yudream.platform.utils.JWTUtils;
import online.yudream.platform.utils.RedisCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.PathContainer;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
/**
* online.yudream.platform.filter
*
* @author SiberianHusky
* * @date 2025/7/5
*/
@Data
@Component
@EqualsAndHashCode(callSuper = false)
@Slf4j
public class CheckTokenFilter extends OncePerRequestFilter {
private String loginUrl = "/login";
// @Autowired
// private AjaxAuthenticationFailureHandler loginFailureHandler;
@Autowired
private UserDetailsService customerUserDetailsService;
private final PathPatternParser pathPatternParser = new PathPatternParser();
@Autowired
private JWTUtils jwtUtils;
@Resource
private RedisCache redisCache;
@Autowired
private SecurityExcludedUrlsConfig excludedUrlsConfig;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws IOException, ServletException {
//获取请求的url(读取配置文件的url)
String url = httpServletRequest.getRequestURI();
if (isExcludedUrl(url)) {
filterChain.doFilter(httpServletRequest, httpServletResponse);
} else {
//token验证(如果不是登录请求 验证toekn)
if (!url.equals(loginUrl)) {
validateToken(httpServletRequest);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
private boolean isExcludedUrl(String url) {
List<PathPattern> patterns = excludedUrlsConfig.getUrls().stream()
.map(pathPatternParser::parse)
.collect(Collectors.toList());
return patterns.stream().anyMatch(pattern -> pattern.matches(PathContainer.parsePath(url)));
}
//token验证
private void validateToken(HttpServletRequest request) {
//从请求的头部获取token
String token = request.getHeader("Authorization");
//如果请求头部没有获取到token,则从请求参数中获取token
if (StringUtils.isEmpty(token)) {
token = request.getParameter("token");
}
if (StringUtils.isEmpty(token)) {
// 请求参数中也没有 那就从redis中进行获取根据ip地址取
token = redisCache.getCacheObject(request.getRemoteAddr());
}
if (StringUtils.isEmpty(token)) {
throw new CustomerAuthenticationException("token不存在!");
}
//解析token
String username = jwtUtils.getTokenInfo(token);
if (StringUtils.isEmpty(username)) {
throw new CustomerAuthenticationException("token解析失败!");
}
//获取用户信息
UserDetails user = customerUserDetailsService.loadUserByUsername(username);
if (user == null) {
throw new CustomerAuthenticationException("token验证失败!");
}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
Java