spring安全自定义usernamepasswordauthenticationfilter不替换默认usernamepasswordauthenticationfilter

w51jfk4q  于 2021-09-30  发布在  Java
关注(0)|答案(1)|浏览(303)

我正在尝试实现我自己的用户名PasswordAuthenticationFilter,它使用firebase auth对来自前端的每个请求进行身份验证。

public class FireBaseAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { 

        .
        .
        //Assigning roles happens here
        List<GrantedAuthority> authorities = new ArrayList<>();
        if (user.getCustomClaims() != null) {
            if (user.getCustomClaims().get("boss").equals("true")) {
                authorities.add(new SimpleGrantedAuthority("boss"));
            }
            if (user.getCustomClaims().get("admin").equals("true")) {
                authorities.add(new SimpleGrantedAuthority("admin"));
            }
            if (user.getCustomClaims().get("office").equals("true")) {
                authorities.add(new SimpleGrantedAuthority("office"));
            }
            if (user.getCustomClaims().get("warehouse").equals("true")) {
                authorities.add(new SimpleGrantedAuthority("warehouse"));
            }
            if (user.getCustomClaims().get("store").equals("true")) {
                authorities.add(new SimpleGrantedAuthority("store"));
            }

            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getUid(), authorities));

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
            user.getEmail(),
                user.getUid(),
                authorities
        );

            }

        filterChain.doFilter(request, response);
    }

}

然后,我尝试替换安全配置中的默认身份验证:

public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().disable().csrf().disable().httpBasic().disable().formLogin().disable()
                .addFilter(new FireBaseAuthenticationFilter())
                .sessionManagement().sessionCreationPolicy(STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

但由于某种原因,我的自定义过滤器在运行时从未被调用?我错过了什么?

wn9m85ua

wn9m85ua1#

例子:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().cors().and().authorizeRequests()
                .antMatchers(HttpMethod.POST, ChallengeConstant.AUTHORIZE_ENDPOINT).permitAll()
                .antMatchers(HttpMethod.POST, ChallengeConstant.TOKEN_ENDPOINT).permitAll()
                .antMatchers(HttpMethod.GET, "/*").permitAll()
                .antMatchers(HttpMethod.GET, "/assets/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(new JWTFilter(userService, objectMapper), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

如果要验证令牌,请执行以下操作:

@AllArgsConstructor
public class JWTFilter extends OncePerRequestFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(JWTFilter.class);
    private final UserService userService;
    private final ObjectMapper objectMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String token = httpServletRequest.getHeader(ChallengeConstant.AUTH_HEADER);
        if (token != null) {
            LOGGER.info("The request is authenticated. Performing Token validity");
            String userName;
            try {
                userName = JWT.require(Algorithm.HMAC512(ChallengeConstant.DUMMY_SIGN.getBytes()))
                        .build()
                        .verify(token.replace(ChallengeConstant.TOKEN_PREFIX, ""))
                        .getSubject();
            } catch (JWTVerificationException ex) {
                LOGGER.warn(String.format("Token is not valid. Token: %s", token), ex);
                generateErrorResponse(httpServletResponse, ExceptionResponse.UNAUTHORIZED);
                return;
            }
            LOGGER.info("Token is valid for username: {}", userName);
            try {
                UserEntity userEntity = userService.findUserByName(userName);
                List<GrantedAuthority> authList = userEntity.getAuthorizations()
                        .stream()
                        .map(authorizationEntity -> new SimpleGrantedAuthority(authorizationEntity.getAuth()))
                        .collect(Collectors.toList());
                SecurityContextHolder.getContext().setAuthentication(
                        new UsernamePasswordAuthenticationToken(userEntity.getUserName(), userEntity.getPassword(), authList));
                LOGGER.debug("User has been found by given username: {} with authorities: {}", userName, authList.toString());
            } catch (NotFoundException ex) {
                LOGGER.warn("User couldn't be found with given username: {}", userName);
                generateErrorResponse(httpServletResponse, ExceptionResponse.NOT_FOUND);
                return;
            }
        }
        LOGGER.info("The request is NOT authenticated. It will continue to request chain.");
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    private void generateErrorResponse(HttpServletResponse httpServletResponse, ExceptionResponse exceptionResponse) throws IOException {
        LOGGER.trace("Generating http error response");
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        httpServletResponse.setStatus(exceptionResponse.getStatus().value());
        ErrorResource errorResource = new ErrorResource(exceptionResponse.getCode(),
                exceptionResponse.getMessage());
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(errorResource));
        LOGGER.trace("Error response is {}", errorResource.toString());
        httpServletResponse.getWriter().flush();
    }

我认为您可以在过滤器中进行验证,如果错误响应无效,则返回错误响应。

相关问题