使用Springboot搭建OAuth2.0 Server的方法示例
作者:iigadmin 发布时间:2023-01-28 07:19:16
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。
OAuth 简介
OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。
基于 OAuth 认证授权具有以下特点:
安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
简单。不管是消费方还是服务提供方,都很容易于理解与使用。
OAuth 的解决方案如下图所示。
图 1. OAuth Solution
如 图 1 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。
从宏观层次来看,OAuth 按以下方式工作:
消费方与不同的服务提供方建立了关系。
消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
消费方根据服务提供方将用户重定向到登录页面。
该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。 前提
阅读本文之前,你需要了解:
Spring Boot
Spring MVC
Spring Security
Google 浏览器插件Postman
pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.iigrowing.study.oauth2</groupId>
<artifactId>demo01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>my.oauth01</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
本项目需要添加的依赖非常简单,一共只有两个,一个是Spring Web,另一个是Spring OAuth2。
接下来是本文的核心,一共三个配置类。
SecurityConfig
package cn.iigrowing.study.oauth2.demo01;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("123456").authorities("ROLE_USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and().csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout().permitAll();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
此处主要做了两件事情:
配置系统用户,这里使用内存存储,添加了用户名为 user
,角色为 USER
的用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("123456").authorities("ROLE_USER");
}
配置了默认表单登陆以及禁用了 csrf
功能,并开启了 httpBasic
认证
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and().csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout().permitAll();
}
AuthorizationServerConfig
package cn.iigrowing.study.oauth2.demo01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client").secret("123456").scopes("read")
.authorizedGrantTypes("authorization_code")
.redirectUris("https://www.getpostman.com/oauth2/callback");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
这个类是OAuth2认证的核心配置类,在这个类中,配置了OAuth Client的信息,这里有几个地方需要注意:
@EnableAuthorizationServer
这个注解告诉 Spring 这个应用是 OAuth2 的授权服务器必须配置
authorizedGrantTypes
,它代表了OAuth Client允许认证的类型,其值主要有:
authorization_code
password
client_credentials
implicit refresh_token
这个配置项接受的类型是个数组,允许配置多个;关于这几种类型的区别,请查看这里不再赘述
redirectUris
关于这个配置项,是在 OAuth2协议中,认证成功后的回调地址,因为稍后我们会使用 Postman
作为测试工具,故此处值固定为 https://www.getpostman.com/oauth2/callback
,此值同样可以配置多个 ResourceServerConfig
package cn.iigrowing.study.oauth2.demo01;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(“users-info”);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.requestMatchers()
.antMatchers(“/users/**”)
.and().authorizeRequests()
.antMatchers(“/users/**”)
.authenticated();
}
}
这个类表明了此应用是OAuth2 的资源服务器,此处主要指定了受资源服务器保护的资源链接,我们将提供以下的资源:
@RestController
@RequestMapping("users")
public class UserController {
@GetMapping("me")
public Principal me(Principal principal) {
return principal;
}
}
注:
资源服务器可以和授权服务器是同一个,也可以分开部署
最后,我们还需添加 application.yml
, 配置资源服务器的filter的顺序
server:
port: 8043
context-path: /uaa
logging:
level:
org.springframework.security: DEBUG
spring:
application:
name: oauth-server
security:
oauth2:
resource:
serviceId: ${PREFIX:}resource
# refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#oauth-2-resource-filter
filter-order: 3
此处的 filter-order
非常重要,因为自Spring Boot 1.5.* 之后,resource server 的 filter 的顺序默认在 basic authentication filter chain
之后,所以如果不配置此项,将会导致使用 access_token
访问 resource server 的时候返回 401
状态码。
来源:http://www.iigrowing.cn/shi_yong_springboot_da_jian_oauth2_0_server.html


猜你喜欢
- 教你一步一步用 java 设计生成二维码在物联网的时代,二维码是个很重要的东西了,现在无论什么东西都要搞个二维码标志,唯恐落伍,就差人没有用
- 1.申请微信公众号我们要进行微信公众平台的开发,第一步当然是要有公众号了。什么?不知道什么是微信公众号,看来你还要先回炉炼炼了,呵呵。通俗的
- 说到多渠道,这里不得不提一下友盟统计,友盟统计是大家日常开发中常用的渠道统计工具,而我们的打包方法就是基于友盟统计实施的。按照友盟官方文档说
- 首先需要在 AndroidManifest.xml 文件中添加「获取模拟定位信息」权限。<uses-permission androi
- 本文是在我的文章android图片处理,让图片变成圆形 的基础上继续写的,可以去看看,直接看也没关系,也能看懂 1、首先在res文
- 倒序拼接字符串@ApiOperation("分页查询") @GetMapping(value
- 在应用登陆页面我们需要填写用户名和密码。当填写这些信息的时候,软键盘会遮挡登陆按钮,这使得用户体验较差,所以今天就来解决这个问题1:登陆布局
- 其实是可以通过@Constraint来限定自定义注解的方法。@Constraint(validatedBy = xxxx.class)下面是
- 换了工作要把Java重新捡起来了,这个在大学里用过的语言,虽然不复杂,还是有一些奇怪的地方的。比如static import。Static
- 目录前言项目环境1.线程池示例2.shutdown3.isShutdown4.isTerminated5.awaitTermination6
- Google 发布的Material Design支持库,对我们的APP设计有很大的影响,如果重新设计APP,支持库应该直接用V4提升到V7
- 上一篇我们学习了自定义ViewGroup的基本步骤,并做了一个CustomGridLayout的实例,这篇我们继续来说说自定义ViewGro
- 游标查询(scroll)简介scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种
- Spring实例Bean的方法Spring实例Bean的方法,在AbstractAutowireCapableBeanFactory中的pr
- Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问。开发Java We
- 本文实例讲述了C#中File类的文件操作方法。分享给大家供大家参考。具体分析如下:File类,是一个静态类,主要是来提供一些函数库用的。静态
- 我正在开发一个软键盘,做得很好,但是我不知道如何自定义一个长按键的弹出窗口.我的键盘视图:<?xml version="1.
- springboot版本:2.2.5一、filter注册springboot中添加filter有两种方式:1、实现方法一package co
- 今天我们来讲一下Android中BroadcastReceiver的相关知识。BroadcastReceiver也就是“广播接收者”的意思,
- spring Boot 熟悉后,集成一个外部扩展是一件很容易的事,集成Redis也很简单,看下面步骤配置:一、添加pom依赖