2017-09-04 25 views
0

JWTとの認証が必要なREST APIを作成しました。JWTトークンを使用している場合、Springブートセキュリティコンテキストがnullを返します

私の実装では、私は現在のユーザーを返すようにしようとすると、私はいつもnullリターンを受け取るhttps://auth0.com/blog/securing-spring-boot-with-jwts/

で見つけたコードと非常によく似ています。

マイコード:

WebSecurity社

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

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は、[OK]を働いているので、私は、JWT認証のすべてのコードが含まれていません、ユーザーアクセス。 問題はフィルタまたはいくつかの設定にあると私は信じています。

public Authentication getAuthentication() { 
    return SecurityContextHolder.getContext().getAuthentication(); 
} 

が、これは働いていません。

その後、私は次のコード(http://www.baeldung.com/get-user-in-spring-securityの方法4)で、serviceまたはcontroller上の現在のユーザーを取得するためにfacadeを作りました。 - SecurityContextHolder.getContext()[email protected]ffffff: Null authenticationが返されました。 - SecurityContextHolder.getContext().getAuthentication()が返されましたnullオブジェクトです。

更新(およびソリューション)

私のコントローラで、私はこのコードを使用した場合、:

SecurityContext context = SecurityContextHolder.getContext(); 
Authentication authentication = context.getAuthentication(); 

を私は、現在のユーザーが、私のサービスでは、まったく同じコードを取得することができます動作しません。 、そして私のサービスはそう

@Async 
public CompletableFuture<Optional<ViewUserDto>> findByLogin(String login) throws InterruptedException { 
... 
} 

非同期(async)で、ここで見つけるコードを使用: しかし、その後、私はSecurityContextは、別のスレッド(https://docs.spring.io/spring-security/site/docs/current/reference/html/concurrency.htmlソース):上の「失われた」であることを覚えてhttps://stackoverflow.com/a/40347437/4794469を、すべてが正常に動作します。 これが私のコードに何らかの副作用をもたらす可能性があるかどうかは分かりません(すべての単体テストが機能します)

答えて

0

WebアプリケーションでJWTを有効にしていたときに同様の問題に直面しました。 「Java Cryptography Extension(JCE)無制限強度管轄ポリシーファイル」が必要です。

  1. このパッケージを下記のURLからダウンロードし、US_export_policy.jar、local_policyを置き換えてください。瓶(\ JRE \ libに\セキュリティ)それはまだ動作しない場合、その後、あなたは場所に上記のjarファイルを交換する必要が

  2. \ libに\セキュリティ

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

+0

これは今でも試しましたが、問題は解決しません。まだnull認証 –

1

Iあなたと同様の承認フローがあるアプリケーションに取り組んできました:

WebSecurityConfigurerAdapterを

@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);    
    } 

} 

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();  
    } 
} 

AbstractAuthenticationProcessingFilter GenericFilterBean

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

@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; 
    } 

} 

コントローラ:

@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; 
    } 
} 
+0

を受け取っていますが、あなたのコードは非常に似ています。 'TokenAuthenticationService'(' UsernamePasswordAuthenticationToken'のインスタンスを返す)を変更した後、私は以前のようにコントローラの現在のユーザを取得できますが、まだFacade(コントローラ外)から取得できません。したがって、今までの私の解決策は、認証されたユーザーをコントローラーからサービスに渡すことです –

関連する問題