在文章article服务下添加一下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--springboot 2.1.3 版本 可能不兼容 spring-security-oauth2-autoconfigure:2.1.0.M4 低版本吧
所以我在上边排除spring-security-oauth2-autoconfigure 依赖-->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
添加**WebSecurityConfig **
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 安全拦截机制(最重要)
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
//所有/r/**的请求必须认证通过
.antMatchers("/r/**").authenticated()
//除了/r/**,其它的请求可以访问
.anyRequest().permitAll();
}
}
====================================================================
资源服务器配置
@EnableResourceServer 注解到一个 @Configuration 配置类上,并且必须使用 ResourceServerConfigurer 这个配置对象来进行配置(可以选择继承自 ResourceServerConfigurerAdapter 然后覆写其中的方法,参数就是这个对象的实例),下面是一些可以配置的属性:
ResourceServerSecurityConfigurer中主要包括:
tokenServices:ResourceServerTokenServices 类的实例,用来实现令牌服务。
tokenStore:TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选
resourceId:这个资源服务的ID,这个属性是可选的,但是推荐设置并在授权服务中进行验证。
其他的拓展属性例如 tokenExtractor 令牌提取器用来提取请求中的令牌。
@Configuration
@EnableResourceServer //自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
/**
* 客户端访问的资源列表
*/
public static final String RESOURCE_ID = "res1";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
//客户端访问的资源列表
.resourceId(RESOURCE_ID)
//验证令牌的服务
.tokenServices(tokenService())
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('all')");
http
// 关闭 csrf
.csrf().disable()
//不创建session不使用session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
验证token
ResourceServerTokenServices 是组成授权服务的另一半,如果你的认证授权服务和资源服务在同一个应用程序上的话,你可以使用 DefaultTokenServices ,这样的话,你就不用考虑关于实现所有必要的接口的一致性问题。如果你的资源服务器是分离开的,那么你就必须要确保能够有匹配认证授权服务提供的 ResourceServerTokenServices,它知道如何对令牌进行解码。
令牌解析方法: 使用 DefaultTokenServices 在资源服务器本地配置令牌存储、解码、解析方式 使用
RemoteTokenServices 资源服务器通过 HTTP 请求来解码令牌,每次都请求认证授权服务器端点 /oauth/check_token
使用认证授权服务的 /oauth/check_token 端点,你需要在认证授权服务将这个端点暴露出去,以便资源服务可以进行访问,这里在上一篇文章中已经提到了。
服务 ResouceServerConfig 中添加代码
/**
* 资源服务令牌解析服务
*
* @return
*/
@Bean
public ResourceServerTokenServices tokenService() {
//使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
RemoteTokenServices service = new RemoteTokenServices();
service.setCheckTokenEndpointUrl("http://localhost:8080/auth/oauth/check_token");
//客户端id
service.setClientId("c1");
//客户端密钥
service.setClientSecret("secret");
return service;
}
注意 service.setCheckTokenEndpointUrl(“http://localhost:8080/auth/oauth/check_token”);
要根据自己项目url来。
测试
启动 auth 服务 , 启动 文章服务
首先我们先来访问 文章服务中的 controller接口 localhost:8081/article/r/r1
直接报401的错误,并且提醒我们:Full authentication is required to access this resourceFull authentication is required to access this resource(访问此资源需要完全身份验证)
因为我们刚才访问的时候没有携带token,所以平台A就不能拿到张三的个人信息,平台A只能去申请令牌,才能继续访问。
上一篇文章中 auth 认证授权服务 已经写完认证授权功能,这里为了演示方便,我就不采取客户端模式,直接用密码模式来演示。
申请令牌
响应结果
{
“access_token”: “148ec1b5-26ce-4b0a-89d0-45fd6155a7a5”,
“token_type”: “bearer”,
“refresh_token”: “a5c199ca-3caf-45a0-85f1-9e43040a8f10”,
“expires_in”: 39859,
“scope”: “all”
}
请求资源
按照oauth2.0协议要求,请求资源需要携带token,如下:
token的参数名称为:Authorization,值为:Bearer access_token值。
注意:在写,Bearer access_token 的时候中间是有一个空格的,
并且请求的参数是放在 headers 里面。
如果token错误(少写一个5),则授权失败
接着测试
修改centroller中的方法,添加一个权限 @PreAuthorize(“hasAnyAuthority(‘p2’)”)
@GetMapping(value = "/r1")
@PreAuthorize("hasAnyAuthority('p2')")
public String r1() {
return "张三的个人信息";
}
先校验一下token,
响应的数据
{
“aud”: [
“res1”
],
“exp”: 1612116736,
“user_name”: “zhangsan”,
“authorities”: [
“admin”,
“p1”
],
“client_id”: “c1”,
“scope”: [
“all”
]
}
我们发现 token:148ec1b5-26ce-4b0a-89d0-45fd6155a7a5 的权限是admin 和p1
但是controller中的方法是: @PreAuthorize(“hasAnyAuthority(‘p2’)”)
重启article 服务