Spring Security:自定义筛选器(JwtAuthenticationFilter)正在被调用,即使我已将特定端点设置为“全部删除”属性

p1iqtdky  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(139)

我已经使用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());
        }

    }
}

请让我知道如果你需要任何其他代码块也!

798qvoo8

798qvoo81#

看起来Spring Security并不知道jwtAuthenticationFilter是一个身份验证过滤器-您从OncePerRequestFilter扩展它。您是否尝试过扩展BasicAuthenticationFilter或AuthenticationFilter?
还有另一个选项-您可以在过滤器本身中指定允许的URL。

相关问题