几天以来,我对春天和假装和探索很陌生。我能够向我们的受保护资源(用户名/密码)发出身份验证请求,并在后续请求标头中使用身份验证服务返回的 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;
}
}