Spring安全+ JWT +认证和hasRole无法正常工作?

时间:2017-12-16 18:17:58

标签: spring-mvc authentication spring-boot spring-security jwt

我的问题是我无法在用户登录时对其进行身份验证。 我认为我的WebSecurityConfig文件存在问题,如下所示:

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

// Web Security

@Autowired
private UserDetailsService userDetailsService;

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

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}


// Authentication and Authorization

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();

    //h2 database console
    http.headers().frameOptions().disable();

    http.exceptionHandling()
            .and().anonymous()
            .and().servletApi()
            .and().headers().cacheControl();
    http.addFilterBefore(
            new JWTLoginFilter("/login", authenticationManager()),
            UsernamePasswordAuthenticationFilter.class);
    http.addFilterBefore(
            new JWTAuthenticationFilter(),
            UsernamePasswordAuthenticationFilter.class);
    http.authorizeRequests()
            .antMatchers(HttpMethod.GET, "/api/**").authenticated()
            .antMatchers(HttpMethod.GET, "/login").permitAll();

    http.logout()
            .logoutUrl("/api/logout")
            .logoutSuccessUrl("/api/index")
            .invalidateHttpSession(true);

}

}

当我使用hasRole("CUSTOMER")时,请回复值message: Access is denied。我不知道问题出在哪里。 几个相关文件: 的 JWTLoginFilter:

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
public JWTLoginFilter(String url, AuthenticationManager authManager) {
    super(new AntPathRequestMatcher(url));
    setAuthenticationManager(authManager);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
    User credentials = new User(request.getParameter("username"),  request.getParameter("email"), request.getParameter("password"));
    return getAuthenticationManager().authenticate(
            new UsernamePasswordAuthenticationToken(
                    credentials.getEmail(),
                    credentials.getPassword(),
                    Collections.emptyList()
            )
    );
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    TokenAuthenticationService.addAuthentication(response, authResult.getName());
}

} 的 JWTAuthenticationFilter:

public class JWTAuthenticationFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) servletRequest);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    filterChain.doFilter(servletRequest, servletResponse);
}

} 的 TokenAuthenticationService

public class TokenAuthenticationService {
static final long EXPIRATIONTIME = 864_000_000; // 10 days
static final String SECRET = "ThisIsASecret";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";

public static void addAuthentication(HttpServletResponse res, String username) {
    String JWT = Jwts.builder()
            .setSubject(username)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();
    res.addHeader(HEADER_STRING, TOKEN_PREFIX+ " " + JWT);
}

public static Authentication getAuthentication(HttpServletRequest request) {
    String token = request.getHeader(HEADER_STRING);

    if (token != null) {
        // parse the token.
        String user = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                .getBody()
                .getSubject();

        return user != null ?
                new UsernamePasswordAuthenticationToken(user, null, emptyList()) :
                null;
    }
    return null;
}

} 请帮我!谢谢!

1 个答案:

答案 0 :(得分:0)

首先,尝试在您的应用程序运行的主应用程序类中创建BCryptPasswordEncoder的Bean,即主方法所在的类。仅在BCryptPasswordEncoder类中初始化WebSecurityConfig对象。 此外,如果您可以共享代码的git repo,那么解决起来会更容易。 Here是我的基本应用程序,它使用JWT和Spring Boot,非常熟悉您的代码。很可能我们都试图从0Auth教程中学习。