前情回顾
前几节分享了OAuth2的流程与其它三种授权模式,这几种授权模式复杂程度由大至小:授权码模式 > 隐式授权模式 > 密码模式 > 客户端模式
本文要讲的是最后一种也是最简单的模式:客户端模式
其中客户端模式的流程是:客户端使用授权服器给的标识与secret访问资源服务器获取token
本文目标
编写与说明密码模式的Spring Security Oauth2的demo实现,让未了解过相关知识的读者对客户端模式授权流程有个更直观的概念
以下分成授权服务器与资源服务器分别进行解释,只讲关键部分,详情见Github:https://github.com/hellxz/spring-security-oauth2-learn
适用场景
没有用户与授权服务器交互,完全以机器形式获取授权与使用授权,客户端机器 <-> 授权服务器
,这种方式主要用于第一方应用中
搭建密码模式授权服务器
代码结构与之前两个模式相同,这里便不再进行说明
SecurityConfig配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
基本的SpringSecurity的配置,开启Spring Security的Web安全功能,填了一个用户信息,所有资源必须经过授权才可以访问
AuthorizationConfig授权服务器配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//@formatter:off
clients.inMemory()
.withClient("user-center")
.secret(passwordEncoder().encode("12345"))
.authorizedGrantTypes("client_credentials") //主要配置这里为client_credentials
.scopes("all");
//@formatter:on
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.checkTokenAccess("isAuthenticated()");
}
}
这里开启了授权服务器的功能,相对其它模式主要是authorizedGrantTypes这里设置的client_credentials,其余不变
application.properties配置sever.port=8080
搭建资源服务器
这里的关键就是ResourceConfig,配置比较简单与其它几个模式完全一致,模式的不同主要表现在授权服务器与客户端服务器上,资源服务器只做token的校验与给予资源
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Bean
public RemoteTokenServices remoteTokenServices(){
final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
remoteTokenServices.setClientId("user-center");
remoteTokenServices.setClientSecret("12345");
return remoteTokenServices;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
http.authorizeRequests().anyRequest().authenticated();
}
}
ResourceController主要接收一个用户名,返回一个username与email的json串
application.properties设置server.port=8081
准备工作到这里就差不多了,开始测试
测试流程
这里客户端使用postman手动发送请求进行演示
-
POST访问/oauth/token端点,获取token
这里除了请求头使用client标识信息外,添加一个grant_type=client_credentials,只需要这两个参数就可以得到token
-
token返回值
{ "access_token": "3efcb9db-2c15-42db-b3f0-3c535439c799", "token_type": "bearer", "expires_in": 43199, "scope": "all" }
-
使用token调用资源,访问http://localhost:8081/user/hellxz001,注意使用token添加Bearer请求头
尾声
本文是OAuth2授权模式代码部分的最后一个,后续分别记录下JWT与Redis两种tokenStore方式