JWT自定义过滤器中的身份验证管理器

时间:2019-05-10 07:13:47

标签: java spring spring-security jwt

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

我曾尝试在Security Configuration类Authentication Manager 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();
    }
}

这是我的JwtAuthenticationFilter

@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 个答案:

答案 0 :(得分:0)

addind 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 Component。