OAuth2 的四种授权模式解析,构建演示 Demo

1,271 阅读4分钟

背景

OAuth2的概念这里不在赘述,有兴趣的同学可以看看我其他相关文章,这里直接干货 演示 OAuth2的 四种授权方式,使用姿势

1 授权码(authorization-code)

1.1 访问获取认证服务器获取授权码code api 如: localhost:7777/oauth/authorize?client_id=cms&response_type=code 然后我们会跳转到认证服务器 登陆地址 企业微信截图_7e2db792-6ad2-48d1-8383-f98411ddb1e9.png

这里通过认证服务器 预先颁发的账号/密匙,登陆进入授权页面

企业微信截图_766d45fb-3962-424c-a7d1-f126a7262449.png

  点击授权之后/ 认证服务器会重定向地址,这里可以取到我们的授权码,如图code=taApM1
  

企业微信截图_634e1eaa-2939-4711-9b46-5ec1c7f95674.png

1.2 通过授权码 code=taApM1 访问获取token api 获取access_token 如图

企业微信截图_3bbde6e0-ac3b-4f05-8ee3-0bacb05ba83b.png

1.3 我们也可以通过认证服务器的access_token 校验api 来校验一下我们获取到的access_token 是否有效 http://localhost:7777/oauth/check_token?token=474f802c-d65c-4e64-aaf2-dfdf034c807c

企业微信截图_6fd11e33-0397-4d00-b75d-eeebc946b40c.png

PS: 这里返回的access_token里面有一个refresh_token信息,有兴趣的同学可以见我的另一篇文章,里面有对refresh_token的作用意义做了讲解  [OAuth2源码分析之 常见面试问题总结回答二 access_token 与 refresh_token](https://juejin.cn/post/7056614367747375118)

1.4 通过拿到的access_token 访问我们需要访问的资源地址demo url

企业微信截图_939ca8fb-5494-4be4-960c-d333ec64d311.png 企业微信截图_9fb93992-b19f-48c9-9cdb-94e51ec4f794.png

2 隐藏式(implicit)

2.1 在授权码模式的基础,直接去掉了获取授权码的过程,相当于直接获取access_token 并且访问目标地址 先在 认证服务器配置重定向url:

public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

```
 @Override
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
     // 使用内存存储
     clients.inMemory()
             .withClient(CLIENT_ID) //标记客户端id
             .secret(passwordEncoder.encode(SECRET_CHAR_SEQUENCE)) //客户端安全码
             .autoApprove(false) //为true 直接自动授权成功返回code
             .redirectUris("http://localhost:7778/resource_server") //重定向uri,uri中携带的必须为这里面填写的之一
             .scopes("app", "file", "zone") //允许授权范围,ALL就不会出现授权页
//                .accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS) //token 时间秒
//                .refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS) //刷新token 时间 秒
             .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT); //允许授权类型
 }
}

企业微信截图_1b416862-35c5-4843-8b46-e393c9b52af4.png

2.2 直接访问获取access_token api地址 localhost:7777/oauth/authorize?response_type=token&client_id=cms&redirect_uri=http://localhost:7778/resource_server 这里的redirect_uri 指的就是你的资源目标访问地址 大家可以看下访问流程 还是会先跳到认证服务器登陆页,进行登陆 登陆之后进行授权 企业微信截图_85291154-b94f-4bed-a794-ee5e81af8b01.png

企业微信截图_75d04187-bad1-4cfb-b7e2-6a08a342ccfe.png

授权之后 会直接跳转到我们的redirect_uri=http://localhost:7778/resource_server 这个地址,并且携带了获取的access_token,如图

企业微信截图_095c529e-b8b3-484e-b461-0463f2c3b9ec.png

2.3 验证刚才步骤2.2获取的access_token 是否有效

企业微信截图_f967ecfa-a977-46d1-b567-080059f36209.png

3 密码式(password)

如果你高度信任某个应用,允许用户把用户名和密码,直接告诉该应用。
该应用就使用你的密码,申请令牌,这种方式称为 密码式(password)/ 例如自家认证的服务器

3.1 前期准备 认证中心配置支持密码式授权

public class OAuth2Configuration extendsAuthorizationServerConfigurerAdapter {
@Override
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
             // 配置密码授权模式
             .and()
             .withClient("cms1")
             .authorizedGrantTypes("password", "refresh_token")
             .scopes("select")
             .authorities("oauth2")
             // user --->  BCryptPasswordEncoder 加密算法生成
             .secret("$2a$10$vrRjc8vlDwv6gBHlv/me8eeRsHO7P3I7ge0F03sr4C3hh/SmS/lMC");
}

public static void main(String[] args) {
 String pass = "user";
 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
 final String passHash = encoder.encode(pass);
 System.out.println(passHash);
 final boolean matches = encoder.matches(pass, passHash);
 System.out.println(matches);
}

// $2a$10$jbVRxqHjW8QIYw7.UFVD/Ocf.7TSKLhZrGJRouTKq/PyTNTQ6TVIa
// true
请注意我这里配置的secret("$2a$10$vrRjc8vlDwv6gBHlv/me8eeRsHO7P3I7ge0F03sr4C3hh/SmS/lMC") 因为我选用的是 BCryptPasswordEncoder加密方式 
即原密码user 对应加密之后是$2a$10$vrRjc8vlDwv6gBHlv/me8eeRsHO7P3I7ge0F03sr4C3hh/SmS/lMC

企业微信截图_2fe4b655-4b90-46e3-a50f-a84719055188.png

3.2 访问认证中心密码模式获取access_token api 地址http://localhost:7777/oauth/token?username=user&password=user&grant_type=password&scope=select&client_id=cms1&client_secret=user 得到access_token 企业微信截图_e7f8fe6a-78e0-4b6a-8753-3cf3ab707d9b.png

3.3 最后校验一下我们通过密码模式获取的access_token看下是否有效 http://localhost:7777/oauth/check_token?token=5691ce5f-686b-40a6-9832-88810792be7f 有效/成功
企业微信截图_c8997c4b-49f7-4f90-92db-7439087681a4.png

4 客户端凭证(client credentials)

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。
严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

4.1 前期准备 认证中心配置支持客户端凭证

public class OAuth2Configuration extendsAuthorizationServerConfigurerAdapter {
@Override
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置客户端授权模式
.and()
.withClient("client_1")
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("select")
.authorities("oauth2")
.secret("$2a$10$vrRjc8vlDwv6gBHlv/me8eeRsHO7P3I7ge0F03sr4C3hh/SmS/lMC");
// 这里的secret和步骤3.1一样 是user加密而来的
}

企业微信截图_f79444f8-b46f-4623-9a9b-277ad58552a7.png

4.2 访问认证中心获取access_token api地址 http://localhost:7777/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=user

企业微信截图_3c33dff6-0b0c-4959-a7f2-d03537b11477.png

4.3 验证一下我们获取的access_token 是否有效 http://localhost:7777/oauth/check_token?token=2ab79cbf-4809-4d90-a68d-fd78de17cb4d 有效/成功

企业微信截图_00277d6f-93f4-443e-ab19-b586ad26fab7.png

源码下载

演示源码demo下载