【Spring Security OAuth】--- 实现标准的OAuth服务提供商


项目源码地址 https://github.com/nieandsun/security

1 项目结构修改+准备工作

1.1 代码改为模块化结构

之前我整个spring-security、spring-social系列文章的代码都没有分模块进行开发,后来想了想还是将其改为模块化结构。下面是我的commit记录,可以看到现在主要有3个分支

  • master分支,《Spring Security开发安全的REST服务》这门课,老师用的代码结构
  • dev-security-module2 我们公司部分项目使用的代码结构
  • dev-security没分模块之前的最后一次提交

在这里插入图片描述

1.2 添加依赖

要使用spring security oauth做服务提供商相关的开发还需要添加如下依赖,同时我还放开了一个spring cloud统一管理jar包版本的依赖,有兴趣的可以通过commit 记录进行查看。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

2 开发认证服务器

Spring Security Oauth对Oauth协议做了很好的封装,我们只需要添加一个配置类就可以完成一个标准的认证服务器的开发了,代码如下:

package com.nrsc.security.app;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

@Configuration
@EnableAuthorizationServer
public class NrscAuthorizationServerConfig {
}

启动项目可以看到控制台打印出如下内容:
在这里插入图片描述
即项目默认为我们指定了一个客户端应用,其client-id 和client-secret如上,默认情况下项目每次重新启动这两个值都会改变。我们可以暂时在yml或properties配置文件里将其指定为固定值,便于后面调试,但真实项目中需要将它们放在数据库里。

security:
  oauth2:
    client:
      # 真实项目中应放在数据库里      
      client-id: nrsc
      client-secret: 123456

3 授权码模式

3.1 访问认证服务器获取授权码

官方文档:https://tools.ietf.org/html/rfc6749#section-4

spring security oauth是Oauth协议的具体实现,访问认证服务器的请求参数可参照Oauth协议官方文挡。

参照Oauth2协议我们拼接的访问认证服务器的url如下:

http://localhost:8080/oauth/authorize?response_type=code&client_id=nrsc&redirect_uri=http://www.example.com&scope=all

其实对上面的URL我觉得看过我QQ和微信授权博客的肯定一点都不陌生了,解释如下:
在这里插入图片描述

  • 问题(1)

但是直接请求会有一点问题,报错如下:
在这里插入图片描述
百度发现,原来是spring security5认证默认改为表单认证的原因 —https://blog.csdn.net/mr_zhuqiang/article/details/82020697
所以需要先将spring security的认证方式改回basic登陆

package com.nrsc.security.app;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //security5+ 认证默认为表单了也就是http.formLogin()
        http.httpBasic();
    }
}
  • 问题2

但是还是有问题,再次请求资源服务器,会报如下错误:
在这里插入图片描述
该错误是说我们必须至少在我们的系统里为客户端用户指定一个redirect_uri,即回调地址。我们可以简单的在yml或properties文件里配置一下:

security:
  oauth2:
    client:
      client-id: nrsc
      client-secret: 123456
      # 可以在这里简单的指定一个或多个redirect-uri,但实际开发中并不会这样做,而是将其放在数据库里
      # 大家可以好好想想为什么资源服务器非要我们指定redirect-uri呢?
      registered-redirect-uri:
        - http://www.example.com
        - http://www.nrsc.com

再次请求认证服务器,会先让我们输入密码,其实这里的用户名和密码指的就是资源所有者的用户名和密码,这里可以联系一下QQ和微信登陆时,我们扫码或输入用户名+密码进行授权的过程.
在这里插入图片描述
当我们输入了用户名yoyo+密码:123456( NRSCDetailsService类中指定的默认密码)后会进入到下面的页面,即询问用户是不是给client-id为nrsc的客户端授予all的权限。
在这里插入图片描述
当选择了Approve,并点击Authorize时,认证服务器就会拿着授权码,跳回到我们指定的 redirect-uri,这样我们就获取到了授权码。
在这里插入图片描述

3.2 拿着授权码换取accessToken

spring security oauth提供的获取accessToken的接口在
package org.springframework.security.oauth2.provider.endpoint包下的TokenEndpoint类里,如下图所示:
在这里插入图片描述
可以看到该接口是一个post请求,请求参数可以参照Oauth2协议官方文档

获取accessToken,参考Oauth2协议官方文档:https://tools.ietf.org/html/rfc6749#section-4.1.3

这里通过Restlet Client工具来发post请求,进行测试:
(1) 在请求头里加入client-id和client-secret信息
在这里插入图片描述
(2)指定Content-Type为application/x-www-form-urlencoded
(3)按照Oauth2协议官方文档指定请求参数
在这里插入图片描述
点击发送后可以获取到accessToken如下:
在这里插入图片描述

4 用户名密码模式

密码模式和授权码模式获取accessToken的接口是一个,但是请求参数不一样:
在这里插入图片描述
注意1:

  • 由于在用户名密码模式里用户的用户名和密码直接放在了客户端,所以这种模式的授权相当于是在客户端完成的
  • 而授权码模式的授权是在认证服务器上完成的

点击发送后可以获取到accessToken如下:
在这里插入图片描述
注意2:这里需要注意,我利用用户名密码模式获取的accessToken和之前利用授权码模式获取的accessToken是一样的,只是expires_in即过期时间比之前少了, 这是因为默认情况下Spring Security Oauth会将某个资源所有者(由用户名+密码进行确定,这里就是yoyo 123456)获取的accessToken保存在内存里一段时间,下次该资源所有者再向认证服务器请求获取accessToken时,如果没超过过期时间,该资源所有者获取到的accessToken都是一样的.

5 开发资源服务器

同开发认证服务器一样,由于Spring Security Oauth对Oauth协议做了很好的封装,我们只需要添加一个配置类就可以完成一个标准的资源服务器的开发了,代码如下:

package com.nrsc.security.app;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
@Configuration
@EnableResourceServer
public class NrscResourcesServerConfig {
}

注意 : 资源服务器和认证服务器只是逻辑上的概念,可以写在同一个配置类里,也可以写在不同的配置类,甚至可以写在不同的项目里.

以后再请求我们的rest接口,就需要每次带上accessToken了,请求如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值