我已经使用spring security来保护我的端点,现在我正在配置我的web应用程序来暴露特定的端点,以便在这些端点上不应用自定义过滤器,但即使我已经给了所有这些端点自定义过滤器也被应用在这些端点上。我还注意到一个行为,即使我从我的config类中删除addFilterBefore属性,这样就不会提到JwtAuthenticationFiter,那么这个过滤器也会在调用这些端点时执行。
我想公开的端点是(/API/users/generate-token)post方法,这是为了在用户第一次登录时生成token,在此请求上应用jwt认证过滤器没有意义
此外,端点(API/user/register)供用户在此注册,在此请求上应用jwt认证过滤器也没有意义
我是Java和Spring 6的新手,我被卡住了,从过去的3天里无法取得任何进展。
非常感谢您的帮助。
我尝试添加安全过滤器链来公开这些特定的端点,并在每个其他端点请求之前添加JwtAuthenticationFilter。
当我用正确的凭证向“/API/users/generate-token”发出post请求时,我希望得到一个生成的令牌作为响应。
SecurityConfig class
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private PasswordEncoderConfig passwordEncoderConfig;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http
.csrf(csrf->csrf.disable())
.cors(cors->cors.disable())
.authorizeHttpRequests(
auth->auth.requestMatchers("/api/users/generate-token", "/api/users/register").permitAll()
.requestMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated())
.exceptionHandling((ex)->ex.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement((session)->session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
System.out.println("http configuration is being used");
//
return http.build();
}
@Bean
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(userDetailsServiceImpl).passwordEncoder(passwordEncoderConfig.passwordEncoder());
return authenticationManagerBuilder.build();
}
}
JwtAuthenticationFilter class
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private JwtAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
System.out.println("jwt authentication fliter is being called");
String username = null;
String jwtToken = null;
if(requestTokenHeader!=null && requestTokenHeader.startsWith("Bearer")){
jwtToken = requestTokenHeader.substring(7);
try {
username = this.jwtUtil.extractUsername(jwtToken);
}catch (ExpiredJwtException e){
e.printStackTrace();
System.out.println("jwt token expired");
}catch (Exception e){
e.printStackTrace();
System.out.println("error");
}
}else {
System.out.println("invalid or token doesn't start with Bearer");
}
//validate
if(username!=null && SecurityContextHolder.getContext().getAuthentication()==null){
final UserDetails userDetails = this.userDetailsServiceImpl.loadUserByUsername(username);
if (this.jwtUtil.validateToken(jwtToken, userDetails)){
//token is valid
UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
usernamePasswordAuthentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthentication);
}else {
System.out.println("invalid token");
}
filterChain.doFilter(request,response);
}
}
}
JwtAuthenticationEntryPoint class
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorised : Server");
}
}
Controller class
@RestController
@RequestMapping("/api/users")
public class AuthenticateController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/generate-token")
public ResponseEntity<JwtResponse> generateToken(@RequestBody JwtRequest jwtRequest) throws Exception {
try{
System.out.println(jwtRequest.getUsername());
System.out.println(jwtRequest.getPassword());
authenticate(jwtRequest.getUsername(),jwtRequest.getPassword());
System.out.println("authentication successful");
}catch (UserNotFoundException e){
e.printStackTrace();
throw new UserNotFoundException("user not found ");
}
UserDetails userDetails = this.userDetailsServiceImpl.loadUserByUsername(jwtRequest.getUsername());
String token = this.jwtUtil.generateToken(userDetails);
System.out.println(token+"hey");
return new ResponseEntity<>(new JwtResponse(token), HttpStatus.OK);
}
private void authenticate(String username, String password) throws Exception {
try{
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}catch (DisabledException e){
throw new Exception("user disabled : "+e.getMessage());
}catch (BadCredentialsException e){
throw new Exception("bad user credentials : "+e.getMessage());
}
}
}
请让我知道如果你需要任何其他代码块也!
1条答案
按热度按时间798qvoo81#
看起来Spring Security并不知道jwtAuthenticationFilter是一个身份验证过滤器-您从OncePerRequestFilter扩展它。您是否尝试过扩展BasicAuthenticationFilter或AuthenticationFilter?
还有另一个选项-您可以在过滤器本身中指定允许的URL。