spring security实战 3-使用授权码模式( Authorization Code grant)保护资源
写在开篇:
在一边翻译,一边学习的过程中,感觉还是将原文改造为更为精小的课程会更为合适,原因在于:
- 这本书本来就是实践课程,本书的目的也是希望大家通过应用,来加深对Spring Security的理解。
- 原文讲述的比较细致,甚至过于细致,例如maven的按照过程,这样的,去除这部分,能更加突出重点。
在改造课程的过程中,我会做到:
- 翻译尊重原文,适当意译。
- 原文提到的知识点我会全部保留
- 所有用例我会做一遍,并对一些部分进行适当补充,或改动。
再次声明,本改编课程源于《OAuth 2.0 Cookbook_Protect Your Web Applications using Spring Security-Packt Publishing(2017)》
课程从第二章开始,在Chaptor2,我们将学习以下内容:
使用授权码模式(Authorization Code grant)保护资源
- 支持隐式授权模式(Implicit grant)
- 使用密码模式(Resource Owner Password Credentials grant type )
- 配置客户端证书授权模式(Client Credentials grant)
- 支持refresh tokens
- 使用一个关系数据库来保存tokens和客户信息
- 使用redis保存token
- 实现客户端注册过程
- 中途破坏Oauth 2.0 Provider
- 使用Gatling,通过共享数据库测试token的验证过程
介绍
我们有一些场景,要求应用在和大量服务进行交互的同时,还要作为分布式系统在网络中提供API。在这样的场景下,用户如果要使用我们的应用程序授权给第三方应用程序,OAuth2.0是一个好的选择。
在这一章,你将学习如何使用OAuth2.0规范所描述的所有授予类型,来创建、配置和分发OAuth2.0 Provider,以覆盖不同场景,同时还将学到如何通过关系数据库和Redis来使用不同的访问令牌管理策略。本章中使用的所有用例都将通过Spring Ontecurity OAuth2.0来实现,在编写这本书的时候,它的版本是2.2.0.RELEASE(在http://projects.spring.io/spr... 中可以查看Spring Ontecurity OAuth2的官方文档)。学习如何配置自己的OAuth2.0 Provider 很重要,因为在当今的应用程序中集成了大量的应用程序。此外,通过阅读本章,您将能够通过使用Spring Security OAuth2.0,实践所有OAuth2细节。
记住,请在在生产中使用TLS/SSL来始终保护客户端和OAuth2.0 Provider之间的所有传输数据,并且贯穿本书的整个实践过程。
Getting ready(配置环境)
安装 java8,maven ,postman/curl
本例使用Spring Security OAuth2 Framework 来实现,此例将不使用任何数据库,我们将用户信息,授权口令都保存在内存中。本例源码可以从https://github.com/PacktPubli... 下载
How to do it
以下步骤将引导你使用Spring Security OAuth2.0 ,来成功配置一个验证服务器和一个资源服务器。
1.使用Spring Initializr (http://start.spring.io)新建一个项目auth-code-server ,增加web,security依赖
2.打开pom.xml,添加如下依赖:
<dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.2.0.RELEASE</version>
</dependency>
注:本例使用的springboot版本为1.5.4.RELEASE,请格外注意版本。
3.打开application.properties ,添加如下内容类来配置auth-code-server 的用户
security.user.name=adolfo
security.user.password=123
4.由于我们想保护用户的资源,所以,现在我们来创建一些待保护的资源,本例中是用户的name和email:
//UserProfile.java
public class UserProfile {private String name;private String email;//getters and setters hidden for brevity
}
5.新建文件UserController.java
,提供endpoint获取用户信息,该endpoint被OAuth2.0保护(在第7步设置)。注意其中的User
来自org.springframework.security.core.userdetails
//UserController.java
@Controller
public class UserController {@RequestMapping("/api/profile")public ResponseEntity<UserProfile> profile() {User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();String email = user.getUsername() + "@mailinator.com";UserProfile profile = new UserProfile();profile.setName(user.getUsername());profile.setEmail(email);return ResponseEntity.ok(profile);}
}
6.现在,已经存在需要被保护的endpoint,那么,我们需要创建OAuth2.0 授权服务,来对访问这个endpoint的请求进行授权
//OAuth2AuthorizationServer.java
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("clientapp").secret("123456").redirectUris("http://localhost:9000/callback").authorizedGrantTypes("authorization_code").scopes("read_profile", "read_contacts");}
}
7.做到第六步,这个应用已经可以通过分发access tokens,给用户授权许可。但是如果想获取用户资源(本例中是Resource Owner profile ),还需要创建资源服务器,用于设置需要被保护的endpoint,放过验证的endpoint等等。下面我们来新建OAuth2ResourceServer类.
//OAuth2ResourceServer.java
@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter{@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().requestMatchers().antMatchers("/api/**");
}
}
至此,我们已经成功搭建了一个资源管理器和一个授权中心。并通过配置,保护匹配/api/**
的请求。
How it works…
如果程序运行正确,我们能从http://localhost:8080/api/profile
拿到用户信息。正常情况下,我们拿到access token,往这个endpoint发请求,可以拿到这样的json字符串:
{"name": "adolfo","email": "adolfo@mailinator.com"}
当然一开始,我们是没有access token的,所以,无论怎样访问,都会提示我们没有验证。那么,我们要如何获取access token呢。这个token是用户批准后获得,在本例中,我们在资源服务器加上 @EnableResourceServer
的标签的同时,意味着,我们将OAuth2AuthenticationProcessingFilter
配置进了Spring Security
的FilterChain
(过滤链). 这个filter将会用来验证任何匹配/api/**
`的请求中,是否携带access token,以及这个token是否是授权中心派发出去的,是否过期等等.
除了资源服务器的配置之外,我们也对授权服务器做了相关配置。可能你发现授权服务器中的代码量很少。使用Spring Security OAuth2.0 框架来配置授权服务器的确很简单,但是在简单的表相背后,隐藏了大量的配置。
通过添加@EnableAuthorizationServer
这个注解,我们实际上导入了一些重要的配置文件(类):
- AuthorizationServerEndpointsConfiguration
AuthorizationServerSecurityConfiguration
AuthorizationServerEndpointsConfiguration
AuthorizationServerEndpointsConfiguration
类对OAuth2.0授权中心有很重要的作用,它定义了这些bean:
- AuthorizationEndpoint
TokenEndpoint
CheckTokenEndpoint
这些bean声明了OAuth2.0的相关endpoint,这些endpoint用于引导验证流程,获取access token和刷新令牌请求。如果你想深入了解每个endpoint是如何工作的,我建议你读一下Spring Security OAuth2 的源码(github可以获取)。通过运行这个例子,我们能够与一些endpoint交互。现在,我们来运行这个例子:
1.启动项目,通过浏览器往服务器发送一下请求:
http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9000/callback&response_type=code&scope=read_profile
因为我们使用的是授权码模式,我们需要将Resource owner重定向到验证页面,这一过程是在“/oauth/authorize”
的endpoint声明的。注意到,我们发送了client_id
, redirect_uri
和 response_type
参数。
如果你想更深入地了解每个参数的意思,可以查看https://tools.ietf.org/html/r...。注意,我们没有发送state参数,用以避免CSRF攻击(我们将会在第8章了解更多详情)。
2.输入我们在application.properties里配置的用户名和密码,
点击login之后,你将被重定向到用户同意页,其中资源所有者可以选择授予第三方应用程序(客户端)的权限的范围。以下页面由Spring security OAuth2.0自动生成,当然也可以轻松被替换为自定义的页面。
3.点击授权后,用户才能重定向回应用程序,这里的重定向地址由redirect_uri
参数决定,如果第一步发送的请求中带有redirect_uri
,则会与我们在OAuth2AuthorizationServer
类中定义的redirectUris
进行匹配验证,如果没有,则直接使用我们在OAuth2AuthorizationServer
中定义的redirectUris
授权之后,重定向请求将带有一个授权码,该授权代码描述用户对指定资源服务器上的指定客户端授予许可的权限。这个授权码看上去是这样的:
http://localhost:9000/callback?code=5sPk8A
4.这个授权码是授权中心随机生成的,客户端用它向授权中心请求access token,可以使用curl工具:
curl -X POST --user clientapp:123456 http://localhost:8080/oauth/token -H "content-type: application/x-www-form-urlencoded" -d "code=5sPk8A&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Fcallback&scope=read_profile"
或者使用postman:
之后,我们能收到这样的回复:
{"access_token": "43c6f525-041f-43c8-b970- 82ba435d3c2c","token_type": "bearer","expires_in": 43199,"scope": "read_profile"
}
这样,我们就拿到了access token.
5.我们现在再用携带access token的url去资源所有者请求资源,同样的,我们可以使用curl:
curl -X GET http://localhost:8080/api/profile -H "authorization: Bearer 43c6f525-041f-43c8-b970-82ba435d3c2c"
或者postman:
这样,我们就拿到想要的资源了。
There's more...
这个例子尽可能编写的简单,但是当我们正式配置一个OAuth 2.0 Provider的时候,应该考虑使用数据库来替换内存来保存客户端的信息。
同样的,我们再次建议使用TLS/SSL来保护客户端与OAuth 2.0 Provider之间的交互。
spring security实战 3-使用授权码模式( Authorization Code grant)保护资源相关推荐
- Spring Security OAuth2 授权码模式 (Authorization Code)
前言 Spring Security OAuth2 授权码模式 (Authorization Code) 应该是授权登录的一个行业标准 整体流程 首先在平台注册获取CLIENT_ID和CLIENT_S ...
- Apache Oltu 实现 OAuth2.0 服务端【授权码模式(Authorization Code)】
要实现OAuth服务端,就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/ 各语言的实现有(我使用了Ap ...
- Spring Security Oauth2 (二) 代码 授权码模式
└─java└─claroja│ Springsecurityoauth2DemoApplication.java│├─config│ AuthorizationServerConfig.java│ ...
- java 授权码模式_Spring Security OAuth2 授权码模式的实现
写在前边 在文章OAuth 2.0 概念及授权流程梳理 中我们谈到OAuth 2.0的概念与流程,这里我准备分别记一记这几种授权模式的demo,一方面为自己的最近的学习做个总结,另一方面做下知识输出, ...
- IdentityServer4系列 | 授权码模式
一.前言 在上一篇关于简化模式中,通过客户端以浏览器的形式请求「IdentityServer」服务获取访问令牌,从而请求获取受保护的资源,但由于token携带在url中,安全性方面不能保证.因此,我们 ...
- PHP下的Oauth2.0尝试 - 授权码授权(Authorization Code Grant)
OAuth 2.0 不太熟悉什么是OAuth2.0的同学可以参考阮大神的文章, 理解OAuth 2.0 - 阮一峰 授权码模式(Authorization Code) # 授权代码授予类型用于获得访问 ...
- Spring Security+Oauth2四种授权模式
上一篇文章:Spring Security + OAuth2.0项目搭建:https://blog.csdn.net/qq_42402854/article/details/123057625 接着认 ...
- oauth2.0授权码模式详解
Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...
- Spring Security OAuth2.0认证授权知识概括
Spring Security OAuth2.0认证授权知识概括 安全框架基本概念 基于Session的认证方式 Spring Security简介 SpringSecurity详解 分布式系统认证方 ...
- OAuth2.0协议入门(一):OAuth2.0协议的基本概念以及使用授权码模式(authorization code)实现百度账号登录
一 OAuth2.0协议的基本概念 (1)OAuth2.0协议 OAuth协议,是一种授权协议,不涉及具体的代码,只是表示一种约定的流程和规范.OAuth协议一般用于用户决定是否把自己在某个服务商上面 ...
最新文章
- Silverlight专题(10)- WatermarkedTextBox使用
- 从朴素贝叶斯到贝叶斯网
- HTML+CSS+JS实现 ❤️鼠标悬停性感美女图片特效❤️
- 如何在程序中打开PDF文件 -C#文章(.net)
- mac gcc安装_16_超级小白Mac Pro下安装superset遇见的坑
- [转载] Java获取嵌套的json串里的返回结果
- 使用hexo搭建github个人博客网站
- Java常用集合类详解
- hdu 5288 OO’s Sequence(计数)
- IOS日历控件JTCalendar
- 基于SSM的房屋租赁管理系统
- CCF-CSP_201812(第15次)
- matplotlib绘图归纳(双纵轴、柱状渐变、堆叠柱状)
- 【VPS折腾记】nextcloud——扩展功能之挂载onedrive(三)
- 还在手动部署 Kubernetes 集群吗,是时候使用 Kubespray 完成自动化部署了!
- Python中低维数组填充高维数组
- 微信朋友圈python广告评论_【Python】我的微信朋友圈分析
- IDF2012媒体日:全新云计算解决方案
- 中文域名是什么意思是?企业有必要注册中文域名吗?
- oracle trace跟踪,oracle数据库跟踪工具 — oracle-tech
热门文章
- jsp 引入java类库报错_myeclipse中运行Jsp项目调用java,运行不了,报错说不能解析jsp中的类型,资源文件无法使用,求解,...
- vue Mutation 必须是同步函数 为什么_Vue知识点——基础篇
- 个性化推荐系统_推荐系统,个性化预测和优点
- php 实现静态链接,在PHP中链接静态方法?
- 用友中标:打造新一代云化ERP 落地大型企业互联网+
- 用云来实现主机效率的最大化 CSC这家公司是怎么做的?
- ubuntu下弹框提醒
- JS中showModalDialog (模态窗口)详细使用
- Skype for Business Server 2015-01-基础环境-准备
- SRM 403(1-250pt, 1-500pt)