当前位置: 首页 > 知识库问答 >
问题:

JWT自定义筛选器中的身份验证管理器

家西岭
2023-03-14

我正在编写一个程序,它使用了带有Spring Security的JWT身份验证。我已经实现了自定义授权和身份验证过滤器。另外,我需要持久化我的令牌,它是由这些过滤器形成的。为此,我创建了令牌DAO服务,它自动连接到过滤器,并用@component注释标记我的过滤器以自动连接该服务。但我无法正确自动执行身份验证管理器。

我尝试在安全配置类中公开身份验证管理器bean,但没有结果。

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@ComponentScan(value = "ua.edu.viti.medex")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    UsersDetailsService usersDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(usersDetailsService).passwordEncoder(encoder());
    }

    @Bean
    public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint)
                .and()
                .authorizeRequests()
                .antMatchers("/signup").hasRole("ADMIN")
                .antMatchers("/login").permitAll()
                .antMatchers("/signout").permitAll()
                .antMatchers("/**").authenticated()
                .and()
                .addFilter(new JwtAuthenticationFilter(authenticationManagerBean()))
                .addFilter(new JwtAuthorizationFilter(authenticationManagerBean()))
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
@Component
@SuppressWarnings({"WeakerAccess", "SpringJavaAutowiredMembersInspection"})
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    TokenServiceImpl tokenService;

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        setAuthenticationManager(authenticationManager);
        setFilterProcessesUrl(SecurityConstants.AUTH_LOGIN_URL);
    }

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

        String body = "";
        if ("POST".equalsIgnoreCase(request.getMethod()))
        {
            try {
                body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        GsonJsonParser jsonParser = new GsonJsonParser();
        Map<String, Object> data = jsonParser.parseMap(body);
        Map<String, Object> credentials = jsonParser.parseMap((String) data.get("data"));

        String username = (String) (credentials != null ? credentials.get("username") : null);
        String password = (String) (credentials != null ? credentials.get("password") : null);

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        return authenticationManager.authenticate(authenticationToken);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain filterChain, Authentication authentication) throws IOException {
        User user = ((User) authentication.getPrincipal());
        Tokens token = null;
        try{
            token = tokenService.getTokenFromEmail(user.getUsername());
        } catch (NotFoundException e) {

        List<String> roles = user.getAuthorities()
                .stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());

        byte[] signingKey = SecurityConstants.JWT_SECRET.getBytes();

        String newToken = Jwts.builder()
                .signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS512)
                .setHeaderParam("typ", SecurityConstants.TOKEN_TYPE)
                .setIssuer(SecurityConstants.TOKEN_ISSUER)
                .setAudience(SecurityConstants.TOKEN_AUDIENCE)
                .setSubject(user.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + 7200000))
                .claim("role", roles)
                .compact();

        String completeToken = SecurityConstants.TOKEN_PREFIX + newToken;
        tokenService.addTokenData(completeToken);
        PrintWriter out = response.getWriter();
        response.setContentType("text/plain");
        response.setCharacterEncoding("UTF-8");
        out.print(completeToken);
        out.flush();
        response.addHeader(SecurityConstants.TOKEN_HEADER, SecurityConstants.TOKEN_PREFIX + newToken);
        return;
        }
        if(token.isValid() && (System.currentTimeMillis() - token.getExpiration().getTime() > 900000)){
            String completeToken = token.getToken();
            PrintWriter out = response.getWriter();
            response.setContentType("text/plain");
            response.setCharacterEncoding("UTF-8");
            out.print(completeToken);
            out.flush();
            response.addHeader(SecurityConstants.TOKEN_HEADER, completeToken);
            return;
        }else {
            String completeToken = null;
            try {
                completeToken = tokenService.refreshToken(token).getToken();
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
            PrintWriter out = response.getWriter();
            response.setContentType("text/plain");
            response.setCharacterEncoding("UTF-8");
            out.print(completeToken);
            out.flush();
            response.addHeader(SecurityConstants.TOKEN_HEADER, completeToken);
        }
    }
}

这个错误是我在尝试构建项目时遇到的。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtAuthenticationFilter' defined in file [D:\Master\MedEx\AuthModule\target\classes\ua\edu\viti\medex\auth\config\secutiry\JwtAuthenticationFilter.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified

共有1个答案

洪建茗
2023-03-14

通过将DAO类添加为构造函数参数解决了问题。

.and()
                .addFilter(new JwtAuthenticationFilter(authenticationManager(), tokenDAO))
                .addFilter(new JwtAuthorizationFilter(authenticationManager(), tokenDAO))
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }

    @Autowired
    TokenDAOImpl tokenDAO;

则没有必要将过滤器作为Spring组件。

 类似资料: