首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用JWT令牌时,上下文返回null

使用JWT令牌时,上下文返回null
EN

Stack Overflow用户
提问于 2017-09-04 20:03:00
回答 2查看 13.2K关注 0票数 7

我已经创建了一个REST,它需要使用JWT进行身份验证。

我的实现非常类似于在https://auth0.com/blog/securing-spring-boot-with-jwts/上找到的代码

当我试图返回当前用户时,我总是收到一个null返回。

我的代码:

Websecurity

代码语言:javascript
复制
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests()
      // login
      .antMatchers(HttpMethod.POST, "/login")
      .permitAll()

      .anyRequest()
      .authenticated()
      .and()
      .addFilterBefore(new JWTLoginFilter(
        "/login", authenticationManager(), logService), UsernamePasswordAuthenticationFilter.class)
      .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}

JWTAuthenticationFilter

代码语言:javascript
复制
public class JWTAuthenticationFilter extends GenericFilterBean {

  @Override
  public void doFilter(
      ServletRequest req,
      ServletResponse res,
      FilterChain filterChain) throws IOException, ServletException {

    Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest)req);

    SecurityContextHolder.getContext().setAuthentication(authentication);
    filterChain.doFilter(req, res);
  }
}

我没有包含JWT身份验证的所有代码,因为JWT工作正常,用户访问也很好。我认为问题在于过滤器或某些配置。

然后,我使用以下代码(方法4在facade上)创建了一个servicecontroller上的当前用户:

代码语言:javascript
复制
public Authentication getAuthentication() {
    return SecurityContextHolder.getContext().getAuthentication();
}

但这不管用。- SecurityContextHolder.getContext()回答org.springframework.security.core.context.SecurityContextImpl@ffffffff: Null authentication。- SecurityContextHolder.getContext().getAuthentication()返回null对象。

更新(和解决方案)

在我的控制器中,如果我使用以下代码:

代码语言:javascript
复制
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();

我可以获得当前用户,但是,在我的服务中,完全相同的代码不能工作。但是,我记得SecurityContext在另一个线程上“丢失”了(源代码:https://docs.spring.io/spring-security/site/docs/current/reference/html/concurrency.html),我的服务是异步的。

代码语言:javascript
复制
@Async
public CompletableFuture<Optional<ViewUserDto>> findByLogin(String login) throws InterruptedException {
...
}

因此,使用这里找到的代码:https://stackoverflow.com/a/40347437/4794469,一切都正常工作。我不知道这是否会给我的代码带来任何副作用(所有单元测试都成功了)

EN

回答 2

Stack Overflow用户

发布于 2017-09-04 22:13:50

我在一个具有类似于您的授权流程的应用程序中工作过:

WebSecurityConfigurerAdapter

代码语言:javascript
复制
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider provider;

    @Autowired
    private TokenAuthenticationService tokenService;

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.authenticationProvider(provider);       
    }

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


        http.authorizeRequests().antMatchers(HttpMethod.POST, "/v1/users", "/v1/oauth/token").permitAll()
            .anyRequest().authenticated()
            .and()          
            .addFilterBefore(new OAuthTokenFilter("/v1/oauth/token", authenticationManager(), tokenService), UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(new AuthorizationFilter(tokenService), UsernamePasswordAuthenticationFilter.class);            
    }   

}

AbstractAuthenticationProcessingFilter

代码语言:javascript
复制
public class OAuthTokenFilter extends AbstractAuthenticationProcessingFilter {

    private final ObjectMapper MAPPER = new ObjectMapper();

    private TokenAuthenticationService service;

    public OAuthTokenFilter(String url, AuthenticationManager manager, TokenAuthenticationService service) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(manager);
        this.service = service;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
        throws AuthenticationException, IOException, ServletException   {       
        Login login = MAPPER.readValue(request.getInputStream(), Login.class);              
        UsernamePasswordAuthenticationToken token = 
                new UsernamePasswordAuthenticationToken(login.getUsername(), login, Arrays.asList());

        return getAuthenticationManager().authenticate(token);
    }


    @Override
    protected void successfulAuthentication(
            HttpServletRequest request, 
            HttpServletResponse response, 
            FilterChain chain,
            Authentication authentication) throws IOException, ServletException {

        User credentials = (User)  authentication.getPrincipal();                   
        String token = service.jwt(credentials);                
        String json = MAPPER.writeValueAsString(new AuthorizationToken(token, "Bearer"));

        response.addHeader("Content-Type", "application/json");
        response.getWriter().write(json);
        response.flushBuffer();     
    }
}

GenericFilterBean

代码语言:javascript
复制
public class AuthorizationFilter extends GenericFilterBean {

    private TokenAuthenticationService service;

    public AuthorizationFilter(TokenAuthenticationService service) {
        this.service = service;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        Authentication authentication = service.getAuthentication((HttpServletRequest)request);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }

}

TokenAuthenticationService

代码语言:javascript
复制
@Service
public class TokenAuthenticationService {

    public static final String JWT_SECRET_ENV = "JWT_SECRET";
    public static final String ISSUER = "my issuer";

    public static final String ROLE_CLAIM = "role";
    public static final String THIRDY_PARTY_ID_CLAIM = "thirdy_party_id";   
    public static final String TOKEN_PREFIX = "Bearer";
    public static final String HEADER = "Authorization";

    @Autowired
    private Environment environment;

    public Authentication getAuthentication(HttpServletRequest request) {
        String token  = request.getHeader(HEADER);      
        String secret = environment.getProperty(JWT_SECRET_ENV);

        if (token != null) {

            try {

                String bearer = token.replace(TOKEN_PREFIX, "").trim();

                Algorithm algorithm = Algorithm.HMAC256(secret);
                JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .build();

                DecodedJWT jwt = verifier.verify(bearer);

                User user = new User();
                user.setId(jwt.getSubject());
                user.setThirdPartyId(jwt.getClaim(THIRDY_PARTY_ID_CLAIM).asString());
                user.setRole(jwt.getClaim(ROLE_CLAIM).asString());

                List<GrantedAuthority> authorities =     AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRole());
                return new UsernamePasswordAuthenticationToken(user, null, authorities);

            } catch (Exception e){
                e.printStackTrace(System.out);
            }
        }

        return null;
    }

}

然后,控制器:

代码语言:javascript
复制
@RestController
public class UserController {

    @ResponseBody
    @GetMapping("/v1/users/{id}")   
    @PreAuthorize("hasAuthority('USER')")
    public User get(@PathVariable("id") String id, Authentication authentication) {     

        User user = (User) authentication.getPrincipal();
        return user;
    }
}
票数 3
EN

Stack Overflow用户

发布于 2017-09-04 20:08:25

当我在我的web应用程序上启用JWT时,我也遇到了类似的问题。您需要:"Java密码扩展(JCE)无限强管辖权策略文件“。

  1. 请从以下网址下载此软件包,并替换US_export_policy.jar,local_policy.jar (\jre\lib\security)
  2. 如果仍然无法工作,则需要替换位置\lib\security中的上述jar文件。

http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46043408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档