上一篇整合介绍了OAuth2的认证服务,接下来利用认证服务提供的token来包含我们的资源。
环境:2.4.12 + OAuth2 + Redis
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.2.11.RELEASE
server:
port: 8088
---
spring:
application:
name: oauth-resource
---
spring:
redis:
host: localhost
port: 6379
password:
database: 1
lettuce:
pool:
maxActive: 8
maxIdle: 100
minIdle: 10
maxWait: -1
public class Users implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
private String id ;
private String username ;
private String password ;
}
@Configuration
@EnableResourceServer
public class OAuthConfig extends ResourceServerConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(OAuthConfig.class) ;
public static final String RESOURCE_ID = "gx_resource_id";
@Resource
private RedisConnectionFactory redisConnectionFactory ;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID) ;
OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator());
resources.authenticationEntryPoint(oAuth2AuthenticationEntryPoint) ;
resources.tokenExtractor((request) -> {
String tokenValue = extractToken(request) ;
if (tokenValue != null) {
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(tokenValue, "");
return authentication;
}
return null;
}) ;
}
private String extractToken(HttpServletRequest request) {
// first check the header... Authorization: Bearer xxx
String token = extractHeaderToken(request);
// sencod check the header... access_token: xxx
if (token == null) {
token = request.getHeader("access_token") ;
}
// bearer type allows a request parameter as well
if (token == null) {
logger.debug("Token not found in headers. Trying request parameters.") ;
token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN) ;
if (token == null) {
logger.debug("Token not found in request parameters. Not an OAuth2 request.") ;
} else {
request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);
}
}
return token;
}
private String extractHeaderToken(HttpServletRequest request) {
Enumeration headers = request.getHeaders("Authorization");
while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that)
String value = headers.nextElement();
if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {
String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();
// Add this here for the auth details later. Would be better to change the signature of this method.
request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,
value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());
int commaIndex = authHeaderValue.indexOf(',');
if (commaIndex > 0) {
authHeaderValue = authHeaderValue.substring(0, commaIndex);
}
return authHeaderValue;
}
}
return null;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable() ;
http.requestMatcher(request -> {
String path = request.getServletPath() ;
if (path != null && path.startsWith("/demo")) {
return true ;
}
return false ;
}).authorizeRequests().anyRequest().authenticated() ;
}
@Bean
public TokenStore tokenStore() {
TokenStore tokenStore = null ;
tokenStore = new RedisTokenStore(redisConnectionFactory) ;
return tokenStore ;
}
@Bean
public WebResponseExceptionTranslator> webResponseExceptionTranslator() {
return new DefaultWebResponseExceptionTranslator() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ResponseEntity translate(Exception e) throws Exception {
ResponseEntity responseEntity = super.translate(e) ;
ResponseEntity
核心配置类主要完整,开启资源服务认证,定义我们需要保护的接口,token的存储对象及错误信息的统一处理。
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping("/res")
public Object res() {
return "success" ;
}
}
测试:
先直接访问token或者传一个错误的tokenj
图片
接下先获取一个正确的token
图片
图片