热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

SpringSecurityOAuth2认证授权示例详解

这篇文章主要介绍了SpringSecurityOAuth2认证授权示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

1.概述

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

1.1 角色

OAuth定义了四个角色

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

OAuth2的交互过程:

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 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 上。

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


推荐阅读
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • REST API 时代落幕,GraphQL 持续引领未来
    尽管REST API已广泛使用多年,但在深入了解GraphQL及其解决的核心问题后,我深感其将引领未来的API设计趋势。GraphQL不仅提高了数据查询的效率,还增强了灵活性和性能,有望成为API开发的新标准。 ... [详细]
  • 本文介绍了如何通过安装 VirtualBox 和 Vagrant 来快速搭建和管理虚拟机环境。我们将详细探讨如何选择合适的 Box 镜像,以及如何高效地下载、添加和管理这些镜像。 ... [详细]
  • 本文探讨了为何采用RESTful架构及其优势,特别是在现代Web应用开发中的重要性。通过前后端分离和统一接口设计,RESTful API能够提高开发效率,支持多种客户端,并简化维护。 ... [详细]
  • APP数据包捕获挑战
    本文探讨了在使用Burp Suite捕获移动应用数据包时遇到的两大难题,尤其是SSL Pinning安全机制的影响,并提供了一种解决方案。 ... [详细]
  • 半导体IP作为芯片设计的关键组成部分,是集成电路开发中的核心要素之一。这种经过验证、可重复使用的模块具备特定功能,通常由第三方供应商提供,能够显著提升设计效率和可靠性,降低开发成本和周期。在现代集成电路设计中,半导体IP的合理选择与应用对项目的成功至关重要。 ... [详细]
  • 本文深入探讨了ASP.NET Web API与RESTful架构的设计与实现。ASP.NET Web API 是一个强大的框架,能够简化HTTP服务的开发,使其能够广泛支持各种客户端设备。通过详细分析其核心原理和最佳实践,本文为开发者提供了构建高效、可扩展且易于维护的Web服务的指导。此外,还讨论了如何利用RESTful原则优化API设计,确保系统的灵活性和互操作性。 ... [详细]
  • SpringBoot非官方教程|终章:文章汇总springboot非官方教程,可能最接近于官方的一个教程,大多数案例都来自于官方文档,为了更好的理解,加入了个人的改造。码云下载:htt ... [详细]
  • restful是这些年的高频词汇了,各大互联网公司也都纷纷推出了自己的restfulapi,其实restful和thrift,grpc类似,就是一种协议,但是这种协议有点特殊的就是 ... [详细]
  • Windows 平台 Ruby on Rails 安装指南
    本文详细介绍如何在 Windows 系统上安装 Ruby 及其开发框架 Rails,包括必要的环境配置和组件安装。 ... [详细]
  • Node.js 开发入门:环境搭建与配置
    随着Node.js技术的日益成熟及其即将发布的1.0稳定版,越来越多的开发者开始关注并尝试这一高性能的服务器端JavaScript平台。本文将引导读者如何在Windows环境下安装配置Node.js,并介绍一些常用的开发工具和框架。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • 为了满足读者需求,InfoQ中文站每周精选并回顾过去的技术新闻,确保重要资讯不会被忽视。本周精选涵盖了多个领域的关键进展,帮助读者在短时间内掌握重要的技术动态和趋势。 ... [详细]
  • php从哪里得到框架(2023年最新分享)
    导读:本篇文章编程笔记来给大家介绍有关php从哪里得到框架的相关内容,希望对大家有所帮助,一起来看看吧。本文目录一览:1、如何用PHP制 ... [详细]
author-avatar
ld无痕的心迹
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有