Spring Security OAuth2认证授权示例详解

本文介绍了如何使用Spring Security OAuth2构建一个授权服务器来验证用户身份以提供access_token,并使用这个access_token来从资源服务器请求数据。

1.概述

OAuth2是一种授权方法,用于通过HTTP协议提供对受保护资源的访问。首先,OAuth2使第三方应用程序能够获得对HTTP服务的有限访问权限,然后通过资源所有者和HTTP服务之间的批准交互来让第三方应用程序代表资源所有者获取访问权限。

1.1 角色

OAuth定义了四个角色

  • 资源所有者 - 应用程序的用户。
  • 客户端 - 需要访问资源服务器上的用户数据的应用程序。
  • 资源服务器 - 存储用户数据和http服务,可以将用户数据返回给经过身份验证的客户端。
  • 授权服务器 - 负责验证用户的身份并提供授权令牌。资源服务器接受此令牌并验证您的身份。

OAuth2的交互过程:

1.2 访问令牌与刷新令牌

访问令牌代表一个向客户授权的字符串。令牌包含了由资源所有者授予的权限范围和访问持续时间,并由资源服务器和授权服务器强制执行。

授权服务器向客户端发出刷新令牌,用于在当前访问令牌失效或过期时获取新的访问令牌,或获取具有相同或更窄范围的其他访问令牌,新的访问令牌可能具有比资源所有者授权的更短的生命周期和更少的权限。根据授权服务器的判断,发布刷新令牌是可选的。

访问令牌的责任是在数据到期之前访问它。
刷新令牌的责任是在现有访问令牌过期时请求新的访问令牌。

2. OAuth2 - 授权服务器

要使用spring Security OAuth2模块创建授权服务器,我们需要使用注解@EnableAuthorizationServer并扩展AuthorizationServerConfigurerAdapter类。

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
	@Autowired
	private BCryptPasswordEncoder passwordEncoder;

	@Override
	public void configure(AuthorizationServerSecurityConfigurer security)
			throws Exception {
		security.tokenKeyAccess("permitAll()")
				.checkTokenAccess("isAuthenticated()")
				.allowFormAuthenticationForClients();
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients)
			throws Exception {
		clients.inMemory().withClient("clientapp")
				.secret(passwordEncoder.encode("654321"))
				.authorizedGrantTypes("password", "authorization_code",
						"refresh_token")
				.authorities("READ_ONLY_CLIENT").scopes("read_user_info")
				.resourceIds("oauth2-resource")
				.redirectUris("http://localhost:8081/login")
				.accessTokenValiditySeconds(5000)
				.refreshTokenValiditySeconds(50000);
	}
}

Spring Security OAuth2会公开了两个端点,用于检查令牌(/oauth/check_token和/oauth/token_key),这些端点默认受保护denyAll()。tokenKeyAccess()和checkTokenAccess()方法会打开这些端点以供使用。

ClientDetailsServiceConfigurer用于定义客户端详细的服务信息,它可以在内存中或在数据库中定义。

在本例中我们使用了内存实现。它具有以下重要属性:

  • clientId - (必需)客户端ID。
  • secret - (可信客户端所需)客户端密钥(可选)。
  • scope - 客户受限的范围。如果范围未定义或为空(默认值),则客户端不受范围限制。
  • authorizedGrantTypes - 授权客户端使用的授权类型。默认值为空。
  • authorities - 授予客户的权限(常规Spring Security权限)。
  • redirectUris - 将用户代理重定向到客户端的重定向端点。它必须是绝对URL。

3. OAuth2 - 资源服务器

要创建资源服务器组件,请使用@EnableResourceServer注解并扩展ResourceServerConfigurerAdapter类。

@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/").permitAll()
			.antMatchers("/api/**").authenticated();
	}
}

以上配置启用/api下所有端点的保护,但可以自由访问其他端点。

资源服务器还提供了一种对用户自己进行身份验证的机制。在大多数情况下,它通常是基于表单的登录。

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.antMatcher("/**")
				.requestMatchers()
				.antMatchers("/oauth/authorize**", "/login**", "/error**")
			.and()
				.authorizeRequests().anyRequest().authenticated()
			.and()
				.formLogin().permitAll();
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth)
			throws Exception {
		auth.inMemoryAuthentication().withUser("peterwanghao")
				.password(passwordEncoder().encode("123456")).roles("USER");
	}

	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
}

4. OAuth2保护的REST资源

本例中只创建了一个RESTful API,它返回登录用户的姓名和电子邮件。

@Controller
public class RestResource {
	@RequestMapping("/api/users/me")
	public ResponseEntity<UserInfo> profile() {
		User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		String email = user.getUsername() + "@126.com";

		UserInfo profile = new UserInfo();
		profile.setName(user.getUsername());
		profile.setEmail(email);

		return ResponseEntity.ok(profile);
	}
}
public class UserInfo {
	private String name;
	private String email;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", email=" + email + "]";
	}
}

5.演示

我们有一个API http://localhost:8080/api/users/me ,我们想通过第三方应用程序来访问API需要OAuth2令牌。

5.1 从用户获取授权许可代码

如上面的序列图所示,第一步是从URL获取资源所有者的授权:

http://localhost:8080/oauth/authorize?client_id=clientapp&response_type=code&scope=read_user_info

通过浏览器访问上面的URL地址,它将展现一个登录页面。提供用户名和密码。对于此示例,请使用“peterwanghao”和“123456”。

登录后,您将被重定向到授予访问页面,您可以在其中选择授予对第三方应用程序的访问权限。

它会重定向到URL,如:http://localhost:8081/login?code=TUXuk9 。这里'TUXuk9'是第三方应用程序的授权代码。

5.2 从授权服务器获取访问令牌

现在,应用程序将使用授权码来获取访问令牌。在这里,我们需要提出以下请求。使用此处第一步中获得的代码。

curl -X POST --user clientapp:654321 http://localhost:8080/oauth/token -H "content-type: application/x-www-form-urlencoded" -d "code=TUXuk9&grant_type=authorization_code&redirect_uri=http://localhost:8081/login&scope=read_user_info"

访问令牌响应

{
  "access_token": "168aad01-05dc-4446-9fba-fd7dbe8adb9e",
  "token_type": "bearer",
  "refresh_token": "34065175-1e92-4bb0-918c-a5a6ece1dc5f",
  "expires_in": 4999,
  "scope": "read_user_info"
}

5.3 从资源服务器访问用户数据

一旦我们有了访问令牌,我们就可以转到资源服务器来获取受保护的用户数据。

curl -X GET http://localhost:8080/api/users/me -H "authorization: Bearer 168aad01-05dc-4446-9fba-fd7dbe8adb9e"

获得资源响应

{
  "name":"peterwanghao",
  "email":"peterwanghao@126.com"
}

6.总结

本文讲解了OAuth2授权框架的实现机制,通过一个例子说明了第三方应用程序如何通过授权服务器的授权去资源服务器上获取受保护的数据。本例的完整代码在GitHub上。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于Spring Security的Oauth2授权实现方法

    前言 经过一段时间的学习Oauth2,在网上也借鉴学习了一些大牛的经验,推荐在学习的过程中多看几遍阮一峰的<理解OAuth 2.0>,经过对Oauth2的多种方式的实现,个人推荐Spring Security和Oauth2的实现是相对优雅的,理由如下: 1.相对于直接实现Oauth2,减少了很多代码量,也就减少的查找问题的成本. 2.通过调整配置文件,灵活配置Oauth相关配置. 3.通过结合路由组件(如zuul),更好的实现微服务权限控制扩展. Oauth2概述 oauth2根据使用场景不同

  • Spring Security OAuth2认证授权示例详解

    本文介绍了如何使用Spring Security OAuth2构建一个授权服务器来验证用户身份以提供access_token,并使用这个access_token来从资源服务器请求数据. 1.概述 OAuth2是一种授权方法,用于通过HTTP协议提供对受保护资源的访问.首先,OAuth2使第三方应用程序能够获得对HTTP服务的有限访问权限,然后通过资源所有者和HTTP服务之间的批准交互来让第三方应用程序代表资源所有者获取访问权限. 1.1 角色 OAuth定义了四个角色 资源所有者 - 应用程序的

  • Spring Security实现分布式系统授权方案详解

    目录 1 需求分析 2 注册中心 3 网关 3.1 创建工程 3.2 token配置 3.3 配置资源服务 3.4 安全配置 4 转发明文token给微服务 5 微服务用户鉴权拦截 6 集成测试 7 扩展用户信息 7.1 需求分析 7.2 修改UserDetailService 7.3 修改资源服务过虑器 1 需求分析 回顾技术方案如下: 1.UAA认证服务负责认证授权. 2.所有请求经过 网关到达微服务 3.网关负责鉴权客户端以及请求转发 4.网关将token解析后传给微服务,微服务进行授权.

  • Spring Security自定义认证逻辑实例详解

    目录 前言 分析问题 自定义 Authentication 自定义 Filter 自定义 Provider 自定义认证成功/失败后的 Handler 配置自定义认证的逻辑 测试 总结 前言 这篇文章的内容基于对Spring Security 认证流程的理解,如果你不了解,可以读一下这篇文章:Spring Security 认证流程 . 分析问题 以下是 Spring Security 内置的用户名/密码认证的流程图,我们可以从这里入手: 根据上图,我们可以照猫画虎,自定义一个认证流程,比如手机短

  • Spring Security 单点登录简单示例详解

    Overview 最近在弄单点登录,踩了不少坑,所以记录一下,做了个简单的例子. 目标:认证服务器认证后获取 token,客户端访问资源时带上 token 进行安全验证. 可以直接看源码. 关键依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2

  • Spring Security短信验证码实现详解

    目录 需求 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证 配置类进行综合组装 需求 输入手机号码,点击获取按钮,服务端接受请求发送短信 用户输入验证码点击登录 手机号码必须属于系统的注册用户,并且唯一 手机号与验证码正确性及其关系必须经过校验 登录后用户具有手机号对应的用户的角色及权限 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证过滤器 综合配置 获取短信验证码 在这一步我们需要写一个controller接收用户的获取验证码请求.注意:一定要为"/sm

  • Spring Security短信验证码实现详解

    目录 需求 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证 配置类进行综合组装 需求 输入手机号码,点击获取按钮,服务端接受请求发送短信 用户输入验证码点击登录 手机号码必须属于系统的注册用户,并且唯一 手机号与验证码正确性及其关系必须经过校验 登录后用户具有手机号对应的用户的角色及权限 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证过滤器 综合配置 获取短信验证码 在这一步我们需要写一个controller接收用户的获取验证码请求.注意:一定要为"/sm

  • go goth封装第三方认证库示例详解

    目录 简介 快速使用 更换 store 总结 简介 当前很多网站直接采用第三方认证登录,例如支付宝/微信/ Github 等.goth封装了接入第三方认证的方法,并且内置实现了很多第三方认证的实现: 图中截取的只是goth支持的一部分,完整列表可在其GitHub 首页查看. 快速使用 本文代码使用 Go Modules. 创建目录并初始化: $ mkdir goth && cd goth $ go mod init github.com/darjun/go-daily-lib/goth 安

  • Spring Security 安全认证的示例代码

    1.1 动态用户 1.1.1 放行资源   如果我们再配置的时候没有放行登录页等一些不需要登录就可以看到的资源,那么访问的时候就会全部拦截导致访问不到.所以我们要配置放行一些无需登录就可以看到的资源. <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:be

  • Spring AOP事务管理的示例详解

    目录 转账案例-环境搭建 步骤1:准备数据库表 步骤2:创建项目导入jar包 步骤3:根据表创建模型类 步骤4:创建Dao接口 步骤5:创建Service接口和实现类 步骤6:添加jdbc.properties文件 步骤7:创建JdbcConfig配置类 步骤8:创建MybatisConfig配置类 步骤9:创建SpringConfig配置类 步骤10:编写测试类 事务管理 转账案例-环境搭建 步骤1:准备数据库表 之前我们在整合Mybatis的时候已经创建了这个表,可以直接使用 create

  • Spring实现泛型注入的示例详解

    目录 1.Spring泛型注入 2. 关于java泛型有四种Type GenericArrayType泛型数组类型 ParameterizedType参数化类型 TypeVariable 类型变量 WildcardType 通配符类型 1.Spring泛型注入 创建一个抽象泛型类BaseDao,有参数化类型T public abstract class BaseDao<T> { public abstract void eat(); } 每种动物有不同的行为,猫.狗 public class

随机推荐