目录
本篇接上篇内容,拿到授权码后,客户端往授权服务器发送请求,携带拿到的授权码,获取对应的access_token,然后可以拿着授权服务器颁发的access_token访问资源服务器。到目前为止,我们暂时只搭建了一个授权服务器,我们通过手动调用接口默认客户端,后续,我们逐步完善。
本篇主要完成的三个任务:
(1)通过获取到的授权码获取access_token
(2)如何搭建一个资源服务器?
(3)通过拿到的access_token如何去访问资源服务器?
1、项目验证
(1)获取授权码
http://localhost:9090/oauth/authorize?client_id=client-code&response_type=code&redirect_uri=http://www.baidu.com
(2)获取access_token
curl --location --request POST 'http://localhost:9090/oauth/token?code=1vnTRV&grant_type=authorization_code&redirect_uri=http://www.baidu.com&scope=read' \
--header 'Authorization: Basic Y2xpZW50LWNvZGU6c2VjcmV0LWNvZGU='
成功获取access_token
{
"access_token": "14b03e41-643b-4f69-8ef8-d4b614905667",
"token_type": "bearer",
"expires_in": 43199,
"scope": "read"
}
①调用
http://localhost:9090/oauth/token?code=1vnTRV&grant_type=authorization_code&redirect_uri=http://www.baidu.com&scope=read 接口获取access_token
②调用该接口需要配置Header头信息,
Authorization Basic Y2xpZW50LWNvZGU6c2VjcmV0LWNvZGU=
Basic后面的值 是 通过base64对字符串 【clientId:secret】进行加密得到的,即我们在授权服务器中配置的【client-code:secret-code】
③请求参数code 即我们获取到的授权码,其他三个参数是固定的
到此,我们搭建了一个授权服务器,然后通过手动调用的方式拿到了access_token。我们调用过程中相当于客户端(client)在与授权服务器进行交互。
2、添加资源服务器
创建一个资源服务器,与授权服务器分离
(1)创建项目
(2)添加依赖
pom.xml中添加依赖,特别说明这是一个父子项目,父pom中添加了spring-boot-dependencies 依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
子项目中oauth2code-resource-server中添加依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
(3)创建启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
(4)配置资源服务器
创建ResourceConfig配置类
@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
// token校验地址 授权服务器地址
private static final String URL_CHECK_TOKEN = "http://localhost:9090/oauth/check_token";
// 分配给资源服务器的clientId
private static final String R_CLIENT_ID = "client-code";
// 分配给资源服务器的SECRET
private static final String R_SECRET = "secret-code";
@Bean
public RemoteTokenServices remoteTokenServices () {
final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl(URL_CHECK_TOKEN);
remoteTokenServices.setClientId(R_CLIENT_ID);
remoteTokenServices.setClientSecret(R_SECRET);
return remoteTokenServices;
}
/**
* 资源服务器访问配置
* TODO 方法描述
* @param http
* @return void
**/
@Override
public void configure(HttpSecurity http) throws Exception{
// 创建session策略
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
// 所有请求都要授权
http.authorizeRequests().anyRequest().authenticated();
}
/**
* 资源服务器配置
* TODO 方法描述
* @param resource
* @return void
**/
@Override
public void configure(ResourceServerSecurityConfigurer resource) {
resource.resourceId("test") // 设置 资源服务器id
.stateless(true) //
.tokenServices(remoteTokenServices()); // 通过远程调用的方式进行token校验;也可以使用tokenstore的方式进行校验
}
}
①注解@Configuration和@EnableResourceServer开启资源服务器
②重写ResourceServerConfigurerAdapter 自定义资源服务器配置
③配置configure(HttpSecurity http)方法,这里可以代替Spring Security同名方法配置,开启所有请求需要授权才可访问
httpsecurity session管理Spring Security Config : HttpSecurity安全配置器 SessionManagementConfigurer_enablesessionurlrewriting-CSDN博客
④configure(ResourceServerSecurityConfigurer resource)资源配置相关,这里配置了resourId/tokenService通过远程调用方式进行token校验
⑤HttpSecurity配置这个与Spring Security类似:
- 请求匹配器,用来设置需要进行保护的资源路径,默认的情况下是保护资源服务的全部路径。
- 通过 http.authorizeRequests()来设置受保护资源的访问规则
- 其他的自定义权限保护规则通过 HttpSecurity 来进行配置。
(5)创建Rest接口
@RestController
@RequestMapping("api")
public class IndexController {
@GetMapping("test")
public Object test() {
return "success";
}
}
(6)添加application.yml
简单配置了端口号
server:
port: 9081
项目最终的结构如下图:
这样我们就创建完成一个资源服务器,并对外暴露了一个rest接口,需要通过携带token进行访问。
3、获取token,访问资源服务器
接下来我们从头走一边,先通过客户端(手动)获取授权码,拿着授权码去授权服务器获取token,然后拿着token去访问资源服务器对外暴露的rest接口。
(1)授权服务器的修改
在上面操作过程中,对授权服务器做了一点处理,添加了认证服务器的一些配置
/**
* 认证服务器配置
* 资源服务器配置了tokenservice后,访问check_token、token_key时不需要授权访问
* @param server
* @return void
**/
@Override
public void configure(AuthorizationServerSecurityConfigurer server) {
server.tokenKeyAccess("permitAll()") // 获取tokenkey的接口不需要授权访问
.checkTokenAccess("permitAll()") // 进行token校验的接口不需要授权访问
.allowFormAuthenticationForClients();
}
因为我们在资源服务器端进行token验证是通过配置RemoteTokenServices 这种形式进行的,而且是两端分离的,所以在认证服务器端需要放开认证权限(或添加适当的认证资源)。不然在访问资源服务器的rest接口时会报错,如下:
报错信息很明显,没有访问check_token的权限。
其实这里我们也可以配置该客户端拥有的资源权限进行限制,比如添加 “是否拥有某种资源”。比如使用hasAnyAuthority('CLIENT') 表示访问 /oauth/check_token时是否拥有CLIENT权限,显然我们在授权服务器的 AuthorizationServerConfig配置文件中对ClientDetailsServiceConfigurer中的配置添加了client(client-code) 拥有资源CLIENT。
/**
* 认证服务器配置
* 资源服务器配置了tokenservice后,访问check_token、token_key时不需要授权访问
* @param server
* @return void
**/
@Override
public void configure(AuthorizationServerSecurityConfigurer server) {
server.tokenKeyAccess("permitAll()") // 获取tokenkey的接口不需要授权访问
.checkTokenAccess("hasAnyAuthority('CLIENT')") // 进行token校验的接口需要有CLIENT这个资源权限
// 这里的CLIENT 是授权服务器 ClientDetailsServiceConfigurer中配置的client的authorities
.allowFormAuthenticationForClients();
}
说到这里,需要了解下authorities/scope
scope:表示权限范围,可选项,用户授权页面时进行选择
authorities:授予client的权限
(2)资源服务器 token校验方式
现在资源服务器的token校验使用的tokenservice 方式,还有tokenStore、tokenExtractor
tokenServices :ResourceServerTokenServices 类的实例,用来实现令牌服务。
tokenStore :TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选。
tokenExtractor 令牌提取器用来提取请求中的令牌。
tokenService():是配置访问资源服务时传过来的令牌解析服务,有两种情况:
资源服务器和认证服务器在一起,这是只需要配置默认的DefaultTokenServices即可,但是要注意必须配置一个TokenStore,即是认证服务器中存储令牌的配置,在本地进行解析验证。
标签:Oauth2,Springboot,配置,SpringSecurity,访问,token,授权,服务器,资源 From: https://blog.csdn.net/dabing9/article/details/143358457资源服务器和认证服务器不在一起,如微服务中的单独认证服务器和多个资源服务器,这是我们需要配置远程令牌访问解析服务RemoteTokenServices ,配置token的验证端点/oauth/check_token,最终将其配置到资源服务器。要注意的是,一定要在认证服务器中开启相应的端点:
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security
// /oauth/token_key公开
.tokenKeyAccess("permitAll()")
// /oauth/check_token公开
.checkTokenAccess("permitAll()")
.allowFormAuthenticationForClients();
}