spring security实战 5-使用密码模式(password grant type)保护资源

写在开篇

本改编课程基于《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的验证过程

​ 本例我们将学习如何配置密码模式,在实践中应该避免使用这种模式,因为这种模式客户端将拿到用户凭证,而这正是应该由Oauth 2.0通过access 代理来解决的事情。从用户凭证共享模式迁移到Oauth 2.0模式时,我们可以选择这种策略。当客户端与Oauth 2.0授权中心在同一solution下(充分信任客户端的情况下)时使用会较为安全。

Getting ready

Java8+maven
可以从https://github.com/PacktPubli… 下载项目源码,这个是书籍官方例子,亲自做过跑过,所以可以放心下载使用。

How to do it…

以下步骤将指导你,使用Spring Security OAuth2 配置一个授权中心和一个资源服务器:

1.使用Spring Initializr 新建一个Springboot工程,加入web,security依赖。
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("password") 
            .scopes("read_profile", "read_contacts"); 
    }
}

7.与《学习3》唯一不同的就是authorizedGrantType的设置,看上去和前两种模式的设置差不多,但是当你直接运行应用时就会报错:

{ 
    "error": "unsupported_grant_type",
     "error_description": "Unsupported grant type: password"
}

8.那是因为,密码模式需要在OAuth2AuthorizationServer 中配置AuthenticationManager

这是完整的OAuth2AuthorizationServer 类:


@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends
        AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.inMemory()
            .withClient("clientapp")
            .secret("123456")
            .authorizedGrantTypes("password")
            .scopes("read_profile", "read_contacts");
    }

}

现在,我们可以启动项目了

How it works…

当我们使用@EnableAuthorizationServer@EnableResourceServer这两个注解时,已经通过spring security配置上oauth2.0的所有支持,正如前几个课程所示。最大的不同,是我们在OAuth2AuthorizationServer中注入了authenticationManager 实例。我们之所以要使用这个实例是因为,授权中心在对第三方,携带access token的请求做出回应时,需要验证资源所有者的证书。

处理配置上的不同,在验证流程上也有所不同。在使用密码模式时,用户(或者称为资源所有者)必须发送凭证(用户名,密码),而这些操作将会在客户端的掌控下。因此,在使用这种模式与客户端和服务端交互时,需要资源所有者必须十分信任客户端。例如,你作为资源所有者与facebook的官方客户端交互,之后有转为与facebook的服务端做交互。

现在,我们来看看,如何使用密码模式来获取资源:

1.首先发送以下请求:

curl -X POST --user clientapp:123456 <http://localhost:8080/oauth/token> -H "accept: application/json" -H "content-type: application/x-www-formurlencoded" -d "grant_type=password&username=adolfo&password=123&scope=read_profile"

或者使用postman:
《spring security实战 5-使用密码模式(password grant type)保护资源》

《spring security实战 5-使用密码模式(password grant type)保护资源》

《spring security实战 5-使用密码模式(password grant type)保护资源》

2.在上一步,我们拿到了access token,现在我们就可以使用这个token来获取资源了,注意,我们在之前没有设置token的过期时间,Spring Security OAuth2默认是43200s。我们应该根据授权模式的不同,设置不同的过期时间,例如隐式模式就应该使用短一些的过期时间。好了,现在我们来请求资源:
《spring security实战 5-使用密码模式(password grant type)保护资源》

curl -X GET <http://localhost:8080/api/profile> -H "authorization: Bearer 28405009-b53d-4e52-bfc3-c8889a477675"

There’s more…

​ 尽管我们建议尽量不要使用密码模式,但是如果当你交互的客户端与服务端(验证中心)都在一个范围内(公司/部门/名下)的时候,可以大胆使用。需要注意的是,客户端不应保留用户的用户名和密码。

    原文作者:Lavender
    原文地址: https://segmentfault.com/a/1190000015602163
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞