上篇文章是授权码模式。
客户端模式
这里记录客户端模式。客户端内部调用时可能会用到该模式客户端模式的参数有四个,grant_type、scope、client_id和client_secret,客户端认证方式不是client_secret_post的客户端发起请求时只用携带grant_type参数即可,其它方式按照各自特点携带客户端的认证信息。
1. 拿token
2. 用token访问接口
grant_type 在客户端模式下固定为client_credentials
client_id:客户端的id
client_secret: 客户端的秘钥
scope:本次请求授权的范围 这个不带的话生成的token也访问不了接口
授权码扩展流程PKCE(Proof Key for Code Exchange)
首先需要添加一个公共客户端并且设置proof key支持,为求方便直接修改AuthorizationConfig.java,之后重启服务,会添加一条适用pkce流程的客户端
/**
* 配置客户端Repository
*
* @param jdbcTemplate db 数据源信息
* @param passwordEncoder 密码解析器
* @return 基于数据库的repository
*/
@Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate
, PasswordEncoder passwordEncoder) {
System.out.println("password encode : " + passwordEncoder.encode("123456"));
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
// 客户端id
.clientId("messaging-client")
// 客户端秘钥,使用密码解析器加密
.clientSecret(passwordEncoder.encode("123456"))
// 客户端认证方式,基于请求头的认证
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
// 配置资源服务器使用该客户端获取授权时支持的方式
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
// 授权码模式回调地址,oauth2.1已改为精准匹配,不能只设置域名,并且屏蔽了localhost,本机使用127.0.0.1访问
// 这里每次启动是不会该数据库的,所以改了这个链接要相应的改一下数据库
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
.redirectUri("https://www.baidu.com/")
.redirectUri("http://127.0.0.1:8080/notify/oauth2/code")
// 该客户端的授权范围,OPENID与PROFILE是IdToken的scope,获取授权时请求OPENID的scope时认证服务会返回IdToken
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
// 自定scope
.scope("message.read")
.scope("message.write")
// 客户端设置,设置用户需要确认授权
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
// 基于db存储客户端,还有一个基于内存的实现 InMemoryRegisteredClientRepository
JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
// 初始化客户端
RegisteredClient repositoryByClientId =
registeredClientRepository.findByClientId(registeredClient.getClientId());
if (repositoryByClientId == null) {
registeredClientRepository.save(registeredClient);
}
// 设备码授权客户端
RegisteredClient deviceClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("device-message-client")
// 公共客户端
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
// 设备码授权
.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
// 自定scope
.scope("message.read")
.scope("message.write")
.build();
RegisteredClient byClientId = registeredClientRepository.findByClientId(deviceClient.getClientId());
if (byClientId == null) {
registeredClientRepository.save(deviceClient);
}
// PKCE客户端
RegisteredClient pkceClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("pkce-message-client")