Spring security + JWT + 经过身份验证并且 hasRole 不起作用?

Posted

技术标签:

【中文标题】Spring security + JWT + 经过身份验证并且 hasRole 不起作用?【英文标题】:Spring security + JWT + authenticated and hasRole not working? 【发布时间】:2018-05-30 15:04:21 【问题描述】:

我的问题是我无法在用户登录时对用户进行身份验证。 我觉得我的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】:

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

【讨论】:

嗨,这是我的回购链接:github.com/homanhluc/…

以上是关于Spring security + JWT + 经过身份验证并且 hasRole 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security----JWT详解

Spring Security+JWT简述

单点登录JWT与Spring Security OAuth

Spring Security OAuth2 v5:NoSuchBeanDefinitionException:'org.springframework.security.oauth2.jwt.Jwt

spring boot + spring security + jwt + React 不工作

Spring Boot + Security + JWT 无法生成令牌