背景

一直对OAuth 2.0的四种授权模式比较好奇,了解的仅限网上的资料,没有使用代码体验过,这次使用spring-security-oauth2来体验这四种模式的整个过程。

相关代码

pom文件

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.1.4.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.4.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.16.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework.security</groupId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
</dependencies>
配置类

@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter { @Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("clientUser")
.secret("{bcrypt}" + new BCryptPasswordEncoder().encode("123456"))
.authorizedGrantTypes("authorization_code", "implicit", "password", "client_credentials");
} @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
UserDetails userDetails = User.withUsername("username")
.password("{bcrypt}" + new BCryptPasswordEncoder().encode("password"))
.roles("123")
.build();
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(userDetails);
daoAuthenticationProvider.setUserDetailsService(inMemoryUserDetailsManager);
AuthenticationManager authenticationManager = new ProviderManager(
Lists.<AuthenticationProvider>newArrayList(daoAuthenticationProvider));
endpoints.authenticationManager(authenticationManager);
}
} @Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
} @Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager(
SecurityProperties properties) {
SecurityProperties.User user = properties.getUser();
List<String> roles = user.getRoles();
return new InMemoryUserDetailsManager(User.withUsername("user")
.password("{bcrypt}" + new BCryptPasswordEncoder().encode("123456"))
.roles(StringUtils.toStringArray(roles)).build());
}
}
启动类

@SpringBootApplication(
exclude = UserDetailsServiceAutoConfiguration.class
// excludeName = "org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration"
)
public class SpringSecurityStudyApplication { public static void main(String[] args) {
SpringApplication.run(SpringSecurityStudyApplication.class, args);
}
}

授权码模式

第一步 访问GET /oauth/authorize

相关代码在org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint

org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint

请求参数和返回结果如下:

返回结果在浏览器上展示的话,是让用户来勾选是否同意授权的一个页面,还有返回结果的_csrf的值要作为第二步的参数。

curl如下:

curl --location --request GET 'http://127.0.0.1:8090/oauth/authorize?response_type=code&client_id=clientUser&redirect_uri=https://www.baidu.com/&scope=scope' \
--header 'Authorization: Basic dXNlcjoxMjM0NTY=' \
--header 'Cookie: JSESSIONID=AB254815273DB81F1F3BAF74E94DAAB6'

第二步 访问POST /oauth/authorize

相关代码在org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint

crul如下:

curl --location --request POST 'http://127.0.0.1:8090/oauth/authorize?user_oauth_approval=true&scope.scope=true&_csrf=a95516db-6ce2-4033-9b81-1060b6c4d829' \
--header 'Cookie: JSESSIONID=73E846796ACB7818E09B93AC4CFD320D'

_csrf 要使用第一步返回的结果,在返回头的Location里可以得到授权码

第一个参数必须要有,因为:

<input name="user_oauth_approval" value="true" type="hidden"/>

@RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL)
public View approveOrDeny(@RequestParam Map<String, String> approvalParameters, Map<String, ?> model, SessionStatus sessionStatus, Principal principal) {
} public static final String USER_OAUTH_APPROVAL = "user_oauth_approval";

第二个参数是用户是否同意授权

第三步 访问POST /oauth/token

相关代码在org.springframework.security.oauth2.provider.endpoint.TokenEndpoint

code 使用第二步的返回结果

crul如下:

curl --location --request POST 'http://127.0.0.1:8090/oauth/token' \
--header 'Authorization: Basic Y2xpZW50VXNlcjoxMjM0NTY=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=5D41BF01BC875BDF266D3C2178537F21' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=1pakV1' \
--data-urlencode 'redirect_uri=https://www.baidu.com/' \
--data-urlencode 'client_id=clientUser' \
--data-urlencode 'scope=scope'

简化模式

第一步 访问GET /oauth/authorize

crul如下:

curl --location --request GET 'http://127.0.0.1:8090/oauth/authorize?response_type=token&client_id=clientUser&redirect_uri=https://www.baidu.com/&scope=scope' \
--header 'Authorization: Basic dXNlcjoxMjM0NTY=' \
--header 'Cookie: JSESSIONID=6AD429F6CF30C10C0E9F1A35EC78A790'

第二步 访问POST /oauth/authorize



crul如下:

curl --location --request POST 'http://127.0.0.1:8090/oauth/authorize?user_oauth_approval=true&scope.scope=true&_csrf=1ba6be5e-845f-47f2-9680-db613adc47c7' \
--header 'Cookie: JSESSIONID=6AD429F6CF30C10C0E9F1A35EC78A790'

密码模式

直接 访问POST /oauth/token

curl如下:

curl --location --request POST 'http://127.0.0.1:8090/oauth/token' \
--header 'Authorization: Basic Y2xpZW50VXNlcjoxMjM0NTY=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=7E149951AB7D3C03E31E21450754DAAE' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=username' \
--data-urlencode 'scope=scope' \
--data-urlencode 'password=password'

客户端模式

直接 访问POST /oauth/token

curl如下:

curl --location --request POST 'http://127.0.0.1:8090/oauth/token' \
--header 'Authorization: Basic Y2xpZW50VXNlcjoxMjM0NTY=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=7E149951AB7D3C03E31E21450754DAAE' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=scope'

参考

理解OAuth 2.0 - 阮一峰

最新文章

  1. 编写可维护的CSS
  2. ReactNative新手学习之路04 组件化开发轮播图swiper支持安卓和IOS
  3. JavaScript系列:正则表达式
  4. FineUI第二天
  5. 学习进度条&lt;第一周&gt;
  6. 代码规范-IAR设置
  7. 九度OJ 1386 旋转数组的最小数字 【算法】
  8. 造成win2008 500内部错误不能显示详细错误的原因和解决方法
  9. Android Service 详解
  10. 【模拟】Codeforces 704A &amp; 705C Thor
  11. JSP1.x 自定义标签
  12. 软考之路--J2SE,从HelloWorld到传世代码
  13. 【LOJ6060】【2017 山东一轮集训 Day1 / SDWC2018 Day1】Set 线性基
  14. Servlet &amp; JSP系列文章总结
  15. 20162322 朱娅霖 作业005&amp;006 栈,队列
  16. 洛谷P1742 最小圆覆盖(计算几何)
  17. Nginx SSL TLS部署最佳实践
  18. shell脚本--分支、条件判断
  19. 脚本加密http://www.datsi.fi.upm.es/~frosal/sources/
  20. JS DOM操作(二) Window.docunment对象——操作样式

热门文章

  1. 攻防世界-MISC:SimpleRAR
  2. xpath &amp; csv文件读写
  3. InnoDB的逻辑存储结构是什么,表空间组成包括哪些?
  4. 10个最危险的Linux命令,希望你牢记在心
  5. 一文说透 MySQL JSON 数据类型(收藏)
  6. Python 什么是flask框架?快速入门
  7. vmware 无法安装 win 10
  8. vscode修改括号对颜色,自定义括号颜色
  9. 1.还不会部署高可用的kubernetes集群?看我手把手教你使用二进制部署v1.23.6的K8S集群实践(上)
  10. 以圆类 Circle 及立体图形类 Solid 为基础设计圆柱类 Cylinder