写在开篇

本改编课程基于《OAuth 2.0 Cookbook_Protect Your Web Applications using Spring Security-Packt Publishing(2017)》。这本书侧重通过一个个精简的小例子来学习,如何使用spring security和oauth2.0来保护你的资源,。

课程从第二章开始,在Chaptor2,我们将学习以下内容:

  1. 使用授权码模式(Authorization Code grant)保护资源

  2. 支持隐式授权模式(Implicit grant)
  3. 使用密码模式(Resource Owner Password Credentials grant type )
  4. 配置客户端证书授权模式(Client Credentials grant)
  5. 支持refresh tokens
  6. 使用一个关系数据库来保存tokens和客户信息
  7. 使用redis保存token
  8. 实现客户端注册过程
  9. 中途破坏Oauth 2.0 Provider
  10. 使用Gatling,通过共享数据库测试token的验证过程

本节为隐式模式的用例,该模式直接运行在浏览器上(例如Javascript 应用)。本例将允许客户端以资源所有者的名义通过OAuth2.0保护的api。

Getting ready

Java 8+maven
源码可从以下链接获取https://github.com/PacktPubli...

How to do it…

接下来的步骤将指导你使用Spring Security OAuth2 搭建一个授权中心和一个资源服务器:

1.使用Spring Initializr 新建一个Springboot工程,加入web,security依赖,本例使用的springboot版本为“1.5.4.RELEASE”。

2.打开pom.xml,加入以下依赖:

<dependency>
 <groupId>org.springframework.security.oauth</groupId>
 <artifactId>spring-security-oauth2</artifactId> 
</dependency>

3.打开application.properties文件,输入:

security.user.name=adolfo
security.user.password=123

4.新建UserProfile类与UserController类,内容与《学习3》中一致,这个是获取资源的接口。

5.新建OAuth2ResourceServer类,内容与《学习3》中一致,这个是资源管理器配置。

6.新建OAuth2AuthorizationServer类,即配置授权中心,注意其中的不同之处:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter{
  @Override
  public void configure(ClientDetailsServiceConfigurer clients)throws Exception{
    clients.inMemory()
      .withClient("clientapp")
      .secret("123456")
      .redirectUris("http://localhost:9000/callback")
      .authorizedGrantTypes("implicit")
      .accessTokenValiditySeconds(120)
      .scopes("read_profile","read_contacts");
    }
}

7.至此,我们已经完成了所有步骤,可以看出,在spring security框架中,授权码模式和隐式模式的构建模式很相似,仅仅在于配置授权中心时,设置不同的authorizedGrantTypes

How it works…

当我们使用@EnableAuthorizationServer@EnableResourceServer 这两个标签时,意味着,我们将Oauth 2.0的 endpoint加入到我们的项目中,与上一节的不同之处在于,我们使用了不同的授权模式,因此验证流程有一点点不同。此外,我们还必须知道的是,我们无需再往/oauth/token 发请求,因为我们现在是隐式模式。

接下来,我们来运行这个项目

1.首先,我们往授权中心发送如下请求:

http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9000/callback&response_type=token&scope=read_profile&state=xyz

注意,此时response_type 的参数值为token ,而不是之前的code。并且,我们的url没有使用编码,此处是作为教学用例所以省略,但在实际生产项目中,请记住要对所有参数进行编码。

当请求到达授权中心的endPoint后,授权中心将会要求资源所有者做身份验证
图片描述

输入用户名密码后,将会跳到授权页面:
图片描述

2.选择所需的scope ,点击Authorize ,你将跳回到之前设置的redirect uri,正如你所见,回调路径携带了我们需要的access token和之前输入的state

http://localhost:9000/callback#access_token=a68fce80-522f-43ee-85d4-6705c34 e555c&token_type=bearer&state=xyz&expires_in=119 

除了access tokenstate,我们还得到了两个参数:token_typeexpires_in。在上一节,使用授权码模式时,也获得了这些返回参数。重要的是要记住,隐式授权类型不允许按照OAuth2规范发布刷新令牌(refresh token)。这种行为是有必要的,它要求在使用运行在浏览器中的程序时,用户必须在场,这样可以在任何需要的时候,给第三方应用授权。

除此之外,授权中心有充分的能力来识别用户的session,避免重复要求资源中心来对客户端进行验证和授权。

隐式模式不允许发布refresh token的另一个理由是,隐式模式是应用在那些无法保护机密数据的公共应用,而这是refresh token要做的。

3.现在我们可以从api/profile 这个endpoint取回用户资料了,就像我们在上一节所做的,记住需携带access token,具体参见上一节

There's more…

当使用隐式模式时,第三方应用始终需要通过重定向URI来注册,这样能确保不会将access token传给不需要验证的客户端。如果不这样做,一些心怀不轨的用户可能先注册一个应用,然后试图让其他的应用来顶替,接收这个access token,这样可能导致灾难性的结果。


Lavender
196 声望59 粉丝

喜欢开发,就酱紫~