men*_*e23 5 spring spring-security cors jwt
我有一个AbstractAuthenticationProcessingFilter我用来处理路径上的POST请求/sign-in.CORS预检请求返回404,因为没有匹配的路径.这对我来说很有意义.
我想知道的是,如果有一种方法可以通知Spring有一个过滤器处理POST(而不是一个控制器),那么Spring可以像控制器处理POST一样调度OPTIONS .用一个控制器写一个控制器是不好的做法PostMapping?我不确定这样做会怎么样,因为技术上过滤器处理POST.
谢谢你的帮助!
更新
这是我的设置.我最初是从手机发布的,因此无法添加这些详细信息.见下文.重申一下,没有控制器/sign-in.POST由JwtSignInFilter.处理.
CORS配置
@EnableWebMvc
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*") // TODO: Lock this down before deploying
.allowedHeaders("*")
.allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())
.allowCredentials(true);
}
}
Run Code Online (Sandbox Code Playgroud)
安全配置
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public JwtSignInFilter signInFilter() throws Exception {
return new JwtSignInFilter(
new AntPathRequestMatcher("/sign-in", HttpMethod.POST.name()),
authenticationManager()
);
}
@Bean
public JwtAuthenticationFilter authFilter() {
return new JwtAuthenticationFilter();
}
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.POST, "/sign-in").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(
signInFilter(),
UsernamePasswordAuthenticationFilter.class
)
.addFilterBefore(
authFilter(),
UsernamePasswordAuthenticationFilter.class
);
}
}
Run Code Online (Sandbox Code Playgroud)
过滤
public class JwtSignInFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private TokenAuthenticationService tokenAuthService;
public JwtSignInFilter(RequestMatcher requestMatcher, AuthenticationManager authManager) {
super(requestMatcher);
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException {
SignInRequest creds = new ObjectMapper().readValue(
req.getInputStream(),
SignInRequest.class
);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
emptyList()
)
);
}
@Override
protected void successfulAuthentication(
HttpServletRequest req,
HttpServletResponse res, FilterChain chain,
Authentication auth) throws IOException, ServletException {
tokenAuthService.addAuthentication(res, auth.getName());
}
}
Run Code Online (Sandbox Code Playgroud)
验证过滤器
public class JwtAuthenticationFilter extends GenericFilterBean {
@Autowired
private TokenAuthenticationService tokenAuthService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Authentication authentication = tokenAuthService.getAuthentication((HttpServletRequest)request);
SecurityContextHolder
.getContext()
.setAuthentication(authentication);
filterChain.doFilter(request, response);
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,终于找到了解决这个问题的方法.经过几个小时的修补和搜索,我发现我需要使用基于过滤器的CORS配置,然后在登录过滤器中处理CORS预检(OPTIONS请求),只需返回200 OK即可.然后CORS过滤器将添加适当的标头.
下面更新了配置(注意我CorsConfig不再需要了,因为我们有一个CORS过滤器SecurityConfig,并且JwtAuthenticationFilter与之前相同).
安全配置
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*"); // TODO: lock down before deploying
config.addAllowedHeader("*");
config.addExposedHeader(HttpHeaders.AUTHORIZATION);
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Bean
public JwtSignInFilter signInFilter() throws Exception {
return new JwtSignInFilter(
new AntPathRequestMatcher("/sign-in"),
authenticationManager()
);
}
@Bean
public JwtAuthenticationFilter authFilter() {
return new JwtAuthenticationFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/sign-in").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(
signInFilter(),
UsernamePasswordAuthenticationFilter.class
)
.addFilterBefore(
authFilter(),
UsernamePasswordAuthenticationFilter.class
);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Run Code Online (Sandbox Code Playgroud)
过滤
public class JwtSignInFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private TokenAuthenticationService tokenAuthService;
public JwtSignInFilter(RequestMatcher requestMatcher, AuthenticationManager authManager) {
super(requestMatcher);
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException {
if (CorsUtils.isPreFlightRequest(req)) {
res.setStatus(HttpServletResponse.SC_OK);
return null;
}
if (!req.getMethod().equals(HttpMethod.POST.name())) {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
return null;
}
SignInRequest creds = new ObjectMapper().readValue(
req.getInputStream(),
SignInRequest.class
);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
emptyList()
)
);
}
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException {
tokenAuthService.addAuthentication(res, auth.getName());
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2394 次 |
| 最近记录: |