一. 什么是OAuth2
“Auth” 表示 “授权” Authorization
“O” 是 Open 的简称,表示 “开放”
连在一起就表示 “开放授权”,OAuth2是一种开放授权协议。
二. OAuth2是什么 怎么用
OAuth2是目前最流行的授权协议,用来授权第三方应用,获取用户数据。 举个例子:快递员想要进入小区,有3种方式。1是业主远程开门,2是业主告诉门禁密码,3是使用令牌(Oauth2)。
令牌和密码的区别:令牌相当于火车票,密码相当于是钥匙。
● 令牌是短期的,自动失效。密码是长期有效。
● 令牌是可以撤销的,撤销立即生效。密码一般不允许他们撤销。
● 令牌有权限范围,如车票座位为10车A15座。密码一般是完整权限。
四.OAuth2的四种授权模式
第一种方式:授权码
授权码(authorization code),指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
这种方式是最常用,最复杂,也是最安全的,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
第二种方式:隐藏式
隐藏式(implicit),也叫简化模式,有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。
RFC 6749 规定了这种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为隐藏式。这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。
第三种方式:密码式
密码式(Resource Owner Password Credentials):如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌。
这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。
第四种方式:凭证式
凭证式(client credentials):也叫客户端模式,适用于没有前端的命令行应用,即在命令行下请求令牌。
这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
五.Spring中的OAuth2
Spring中的实现
具体参考官网OAuth2 :: Spring Security
Spring Security
-
客户应用(OAuth2 Client):OAuth2客户端功能中包含OAuth2 Login
-
资源服务器(OAuth2 Resource Server)
-
Spring
-
授权服务器(Spring Authorization Server):它是在Spring Security之上的一个单独的项目。
相关依赖
<!-- 资源服务器 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency><!-- 客户应用 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency><!-- 授权服务器 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
授权登录的实现思路
使用OAuth2 Login
GiuHub社交登录案例
创建应用
注册客户应用:
登录GitHub,在开发者设置中找到OAuth Apps,创建一个application,为客户应用创建访问GitHub的凭据:
填写应用信息:默认的重定向URI模板为{baseUrl}/login/oauth2/code/{registrationId}
。registrationId是ClientRegistration的唯一标识符。
获取应用程序id,生成应用程序密钥:
创建测试项目
创建一个springboot项目oauth2-login-demo,创建时引入如下依赖
application.yml:
spring:security:oauth2:client:registration:github:client-id: 7807cc3bb1534abce9f2client-secret: 008dc141879134433f4db7f62b693c4a5361771b
# redirectUri: http://localhost:8200/login/oauth2/code/github
创建Controller
@Controller
public class IndexController {@GetMapping("/")public String index(Model model,@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,@AuthenticationPrincipal OAuth2User oauth2User) {model.addAttribute("userName", oauth2User.getName());model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());model.addAttribute("userAttributes", oauth2User.getAttributes());return "index";}
}
创建html页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head><title>Spring Security - OAuth 2.0 Login</title><meta charset="utf-8" />
</head>
<body>
<div style="float: right" th:fragment="logout" sec:authorize="isAuthenticated()"><div style="float:left"><span style="font-weight:bold">User: </span><span sec:authentication="name"></span></div><div style="float:none"> </div><div style="float:right"><form action="#" th:action="@{/logout}" method="post"><input type="submit" value="Logout" /></form></div>
</div>
<h1>OAuth 2.0 Login with Spring Security</h1>
<div>You are successfully logged in <span style="font-weight:bold" th:text="${userName}"></span>via the OAuth 2.0 Client <span style="font-weight:bold" th:text="${clientName}"></span>
</div>
<div> </div>
<div><span style="font-weight:bold">User Attributes:</span><ul><li th:each="userAttribute : ${userAttributes}"><span style="font-weight:bold" th:text="${userAttribute.key}"></span>: <span th:text="${userAttribute.value}"></span></li></ul>
</div>
</body>
</html>
启动应用程序
- 启动程序并访问localhost:8080。浏览器将被重定向到默认的自动生成的登录页面,该页面显示了一个用于GitHub登录的链接。
- 点击GitHub链接,浏览器将被重定向到GitHub进行身份验证。
- 使用GitHub账户凭据进行身份验证后,用户会看到授权页面,询问用户是否允许或拒绝客户应用访问GitHub上的用户数据。点击允许以授权OAuth客户端访问用户的基本个人资料信息。
- 此时,OAuth客户端访问GitHub的获取用户信息的接口获取基本个人资料信息,并建立一个已认证的会话。
登录流程分析
- A 网站让用户跳转到 GitHub,并携带参数ClientID 以及 Redirection URI。
- GitHub 要求用户登录,然后询问用户"A 网站要求获取用户信息的权限,你是否同意?"
- 用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码。
- A 网站使用授权码,向 GitHub 请求令牌。
- GitHub 返回令牌.
- A 网站使用令牌,向 GitHub 请求用户数据。
- GitHub返回用户数据
- A 网站使用 GitHub用户数据登录