PS:此文章為系列文章,建議從第一篇開始閱讀。
資源服務器配置
@EnableResourceServer 注解到一個@Configuration配置類上,並且必須使用ResourceServerConfigurer 這個配置對象來進行配置(可以選擇繼承自ResourceServerConfigurerAdapter然后覆寫其中的方法,參數就是這個對象的實例),下面是一些可以配置的屬性:
- ResourceServerSecurityConfigurer中主要包括:
-
tokenServices :ResourceServerTokenServices 類的實例,用來實現令牌服務。
-
tokenStore :TokenStore類的實例,指定令牌如何訪問,與tokenServices配置可選
-
resourceId :這個資源服務的ID,這個屬性是可選的,但是推薦設置並在授權服務中進行驗證
-
其他的拓展屬性例如 tokenExtractor 令牌提取器用來提取請求中的令牌。
- HttpSecurity配置這個與Spring Security類似:
-
請求匹配器,用來設置需要進行保護的資源路徑,默認的情況下是保護資源服務的全部路徑。
-
通過 http.authorizeRequests()來設置受保護資源的訪問規則
-
其他的自定義權限保護規則通過 HttpSecurity 來進行配置。
具體的配置信息如下:
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class DimplesResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "dimples";
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)
.tokenServices(tokenService())
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// 配置客戶端權限scope
.antMatchers("/**").access("#oauth2.hasScope('all')")
.and().csrf().disable()
// 關閉session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
/**
* 資源服務令牌解析服務,調用遠程服務解析
*/
/*@Bean
public ResourceServerTokenServices tokenService() {
//使用遠程服務請求授權服務器校驗token,必須指定校驗token 的url、client_id,client_secret
RemoteTokenServices service = new RemoteTokenServices();
service.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
service.setClientId("dimples");
service.setClientSecret("123456");
return service;
}*/
/**
* 資源服務器令牌解析服務,資源和認證在一起,不用調用遠程
*
* @return ResourceServerTokenServices
*/
@Bean
@Primary
public ResourceServerTokenServices tokenService() {
DefaultTokenServices services = new DefaultTokenServices();
// 必須設置
services.setTokenStore(tokenStore);
return services;
}
}
tokenService():是配置訪問資源服務時傳過來的令牌解析服務,有兩種情況:
-
資源服務器和認證服務器在一起,這是只需要配置默認的DefaultTokenServices即可,但是要注意必須配置一個TokenStore,即是認證服務器中存儲令牌的配置,在本地進行解析驗證。
-
資源服務器和認證服務器不在一起,如微服務中的單獨認證服務器和多個資源服務器,這是我們需要配置遠程令牌訪問解析服務RemoteTokenServices ,配置token的驗證端點/oauth/check_token,最終將其配置到資源服務器。要注意的是,一定要在認證服務器中開啟相應的端點:
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security
// /oauth/token_key公開
.tokenKeyAccess("permitAll()")
// /oauth/check_token公開
.checkTokenAccess("permitAll()")
.allowFormAuthenticationForClients();
}
- 如果是資源服務分離情況下,還需要配置Security一個安全控制
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
/**
* 安全攔截機制(最重要)
*/
@Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf().disable()
.authorizeRequests()
//所有/user/**的請求必須認證通過
.antMatchers("/user/**").authenticated()
//除了/user/**,其它的請求可以訪問
.anyRequest().permitAll();
}
}
測試資源服務器
新建controller訪問鏈接
@RestController
@RequestMapping("user")
public class UserController {
@GetMapping
@PreAuthorize("hasAuthority('admin')")
public DimplesUser user() {
DimplesUser user = new DimplesUser();
user.setUserName("username");
return user;
}
}
先通過密碼模式獲取token
然后帶上獲取的token去訪問相應的資源
token傳輸格式為 在OAuth2.0中規定:
- token必須放在Header中
- 對應的格式為:token的參數名稱為:Authorization,值為:Bearer token值
如果傳錯誤的token
或者不傳token