3

几天以来,我对春天和假装和探索很陌生。我能够向我们的受保护资源(用户名/密码)发出身份验证请求,并在后续请求标头中使用身份验证服务返回的 JWT 令牌。但是,我只想在令牌过期时使用相同的凭据调用身份验证服务。Spring 云具有 OAuth2FeignRequestInterceptor,它执行完全相同的操作,但使用客户端 ID 和密钥。

任何此类用于处理由用户名和密码生成的令牌的自定义拦截器?

4

3 回答 3

6

If your JWT token provider is OAuth 2.0 compliant, you can configure the OAuth2FeignRequestInterceptor, with an OAuth2ProtectedResourceDetails object. This object is the base class for all OAuth 2.0 grant type information. In your case, I recommend using ResourceOwnerPasswordResourceDetails instead. This will allow you to configure an interceptor using a username and password.

@Configuration
public class OAuth2RequestInterceptorConfiguration {

    @Bean
    public OAuth2FeignRequestInterceptor requestInterceptor() {
        OAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
        OAuth2ProtectedResourceDetails resourceDetails =
            new ResourceOwnerPasswordResourceDetails();
        resourceDetails.setUsername("username");
        resourceDetails.setPassword("password");
        return new OAuth2FeignRequestInterceptor(clientContext, resourceDetails);
    }
}

For other cases, you will need to create your own RequestInterceptor

public class MyRequestInterceptor implements RequestInterceptor {

    private String jwt;
    private LocalDateTime expirationDate;

    @Override
    public void apply(RequestTemplate requestTemplate) {
        /* validate and refresh your token, this sample is not thread safe */
        if (LocalDateTime.now().isAfter(expirationDate)) {
            requestToken();
        }

        /* use the token */
        requestTemplate.header("Authorization: Bearer " + this.jwt);
    }
}
于 2018-04-30T17:07:31.477 回答
2

您可以尝试以下方法:

public class FeignConfiguration {

    @Value("${security.jwt.token}")
    private String jwtToken;

    @Bean
    public RequestInterceptor requestInterceptor() {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            requestTemplate.header("Authorization", jwtToken);
        }
    }
}
于 2019-05-16T22:24:55.647 回答
0

在用例上并不完全清楚,但也许下面的代码片段也会很有用。我们的服务需要一个签名的 OAuth Bearer JWT访问令牌。您可以看到我们在 JWT 过期时显式验证,当 JWT 令牌过期时我们返回错误。在我们的设置中,消费者有责任捕获此错误并在这种情况发生时使用刷新令牌(检索新的访问令牌)。

希望这能澄清一点。

/**
 * Created by Wim Van den Brande on 11/02/2018.
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);

    public static final String SCOPE = "scope";
    public static final String HEADER_AUTHORIZATION = "Authorization";
    public static final String HEADER_BEARER = "Bearer";
    public static final String HEADER_ENCRYPTION_TYPE = "Encryption-Type";
    public static final String ASSYMETRIC_ENCRYPTION_RS256 = "RS256";

    @Value("${CS.signedPublicKey}")
    private String signedPublicKey;

    @Autowired
    private Key signinKey;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // TODO : to enable CSRF
        http.httpBasic().and().csrf().disable();

        TokenAuthenticationFilter tokenFilter = new TokenAuthenticationFilter();
        http.addFilterBefore(tokenFilter, BasicAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/admin", "/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**");
    }

    // Actual Implementation of Token Based Authentication
    // ---------------------------------------------------
    public class TokenAuthenticationFilter extends GenericFilterBean {

        @Override
        public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
            final HttpServletRequest httpRequest = (HttpServletRequest) request;
            final HttpServletResponse httpResponse = (HttpServletResponse) response;

            String authorizationHeader = httpRequest.getHeader(HEADER_AUTHORIZATION);

            if (authorizationHeader == null) {
                    httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, String.format("Request doesn't contain header %s.", HEADER_AUTHORIZATION));
                    return;
            }

            String[] authorizationHeaderValues = authorizationHeader.split("\\s+");

            if (authorizationHeaderValues.length != 2 || !authorizationHeaderValues[0].equals(HEADER_BEARER)) {
                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, String.format("AuthorizationHeader %s is an invalid header ", authorizationHeader));
                return;
            }

            String accessToken = authorizationHeaderValues[1];
            Claims jwtClaims;

            // Symmetric Encryption is our default

            if (httpRequest.getHeader(HEADER_ENCRYPTION_TYPE) == null || !httpRequest.getHeader(HEADER_ENCRYPTION_TYPE).equals(ASSYMETRIC_ENCRYPTION_RS256)) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Using Symmetric algorithm");
                }

                try {
                    jwtClaims = Jwts.parser().setSigningKey(signinKey).parseClaimsJws(accessToken).getBody();
                }
                catch (ExpiredJwtException e) {
                    httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JSON Web Token has expired");
                    return;
                }
            }
于 2018-05-02T06:24:25.700 回答