权限认证(五):OAuth2资源服务器
重点
认证服务器和资源服务器是服务端,可以看成是微信;
第三方客户端则是客户端,可以看成第三方的网站
用户在认证服务器认证成功后,再去资源服务器获取用户的相关资源
资源服务器是提供给第三方客户端使用的
如果没有第三方客户端,所有子模块都是自己内部的子系统,则使用单点登录即可
- 新建一个demo06,在demo05的基础上开发,确保能够跑通
- 由于使用jdbc管理第三方应用,所以查看数据库
- 任意使用一种模式获取token
- 检查该令牌是否有效,查看拥有的权限
- 测试通过
资源服务器的使用
- 新建子模块resource
- 编写pom.xml
<dependencies>
<dependency>
<artifactId>base</artifactId>
<groupId>com.ychen.oauth2</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--spring mvc相关的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security、OAuth2 和JWT等 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!-- springboot 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--热部署 ctrl+f9-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 编写启动类
@SpringBootApplication
public class ProductResourceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductResourceApplication.class, args);
}
}
- 编写控制层接口,模拟一些资源
@RestController
@RequestMapping("/product")
public class ProductController {
@GetMapping("/list")
@PreAuthorize("hasAuthority('product')")
public MengxueguResult list() {
List<String> list = new ArrayList<>();
list.add("眼镜");
list.add("格子衬衣");
list.add("双肩包");
return MengxueguResult.ok(list);
}
}
- 拓展
@PreAuthorize("hasAuthority('product')")
# 表示在令牌有效的前提下,还要拥有product权限才能访问该资源,即如下检查令牌时查看是否拥有权限
- 编写配置类
@Configuration
@EnableResourceServer // 标识为资源服务器,请求服务中的资源,就要带着token过来,找不到token或token是无效访问不了资源
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别权限控制
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "product-server";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 当前资源服务器的资源id,认证服务会认证客户端有没有访问这个资源id的权限,有则可以访问当前服务
resources.resourceId(RESOURCE_ID)
.tokenServices(tokenService())
;
}
public ResourceServerTokenServices tokenService(){
// 远程认证服务器进行校验 token 是否有效
RemoteTokenServices service = new RemoteTokenServices();
// 请求认证服务器校验的地址,默认情况 这个地址在认证服务器它是拒绝访问,要设置为认证通过可访问
service.setCheckTokenEndpointUrl("http://localhost:8090/auth/oauth/check_token");
service.setClientId("mengxuegu-pc");
service.setClientSecret("mengxuegu-secret");
return service;
}
}
- 拓展
RESOURCE_ID = "product-server"
# 表示在认证服务器中认证成功后,配置了可以访问的资源,由于认证服务器中配置的是product-server,所以为了测试这个资源服务器先配置为product-server
# 检查令牌时,可查看该token可访问的资源id
- 启动认证服务器模块和资源服务器模块进行测试
- 浏览器访问如下,获取授权码
http://localhost:8090/auth/oauth/authorize?client_id=mengxuegu-pc&response_type=code
-
输入用户名和密码,并同意授权,之后得到一个授权码
-
通过授权码模式得到一个token
-
检查令牌是否有效,有效则可以查看拥有的权限
-
拿到令牌去资源服务器获取资源,测试通过
资源服务器的权限配置
# 当用户在认证服务器中使用授权码模式,获取授权码的时候,会指定第三方的客户端可以访问服务端的哪些资源
# 而资源服务器的权限配置,则是用于限制服务端的不同资源需要不同的权限
# 第1层权限:RESOURCE_ID = "product-server";表示访问当前资源服务器需要的权限
# 第2层权限:scope=all,表示访问该资源服务器中的某些资源所需的权限
# 第3层权限:.antMatchers("/product/*").hasAuthority("product");表示具体某个接口所需的权限
- 代码实现
# ResourceServerConfig配置类下添加如下
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
// SpringSecurity不会使用也不会创建HttpSession实例
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 授权规则配置,表示拥有product权限的token才能访问/product/*路径下的接口
.antMatchers("/product/*").hasAuthority("product")
// 所有请求,都需要有all范围(scope)
.antMatchers("/**").access("#oauth2.hasScope('all')")
// 等价于上面
// .anyRequest().access("#oauth2.hasScope('all')")
;
}
- 拓展
.antMatchers("/product/*").hasAuthority("product")
# 表示拥有product权限的令牌才能访问/product/*路径下的资源,可在检查令牌时查看拥有的权限
.antMatchers("/**").access("#oauth2.hasScope('all')")
# 表示拥有all授权标识的令牌才能访问/**路径下的资源,可在检查令牌时查看拥有的授权标识