几天以来,我对春天和假装和探索很陌生。我能够向我们的受保护资源(用户名/密码)发出身份验证请求,并在后续请求标头中使用身份验证服务返回的 JWT 令牌。但是,我只想在令牌过期时使用相同的凭据调用身份验证服务。Spring 云具有 OAuth2FeignRequestInterceptor,它执行完全相同的操作,但使用客户端 ID 和密钥。
任何此类用于处理由用户名和密码生成的令牌的自定义拦截器?
几天以来,我对春天和假装和探索很陌生。我能够向我们的受保护资源(用户名/密码)发出身份验证请求,并在后续请求标头中使用身份验证服务返回的 JWT 令牌。但是,我只想在令牌过期时使用相同的凭据调用身份验证服务。Spring 云具有 OAuth2FeignRequestInterceptor,它执行完全相同的操作,但使用客户端 ID 和密钥。
任何此类用于处理由用户名和密码生成的令牌的自定义拦截器?
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);
}
}
您可以尝试以下方法:
public class FeignConfiguration {
@Value("${security.jwt.token}")
private String jwtToken;
@Bean
public RequestInterceptor requestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("Authorization", jwtToken);
}
}
}
在用例上并不完全清楚,但也许下面的代码片段也会很有用。我们的服务需要一个签名的 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;
}
}