1. 概述
1.1 OAuth2.0 是什么?
OAuth(Open Authorization)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。
每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的 2 小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth 让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。
OAuth2.0 是用于授权的行业标准协议。OAuth2.0 为简化客户端开发提供了特定的授权流,包括 Web 应用、桌面应用、移动端应用等。
1.2 OAuth2.0 角色解释
Authorization Server:认证服务器,用于认证用户。如果客户端认证通过,则发放访问资源服务器的令牌。 Resource Server:资源服务器,拥有受保护资源。如果请求包含正确的访问令牌,则可以访问资源。 Client:客户端。它请求资源服务器时,会带上访问令牌,从而成功访问资源。
Resource Owner:资源拥有者。最终用户,他有访问资源的账号与密码。
1.3 OAuth 2.0 运行流程
如下是 OAuth 2.0 的授权码模式的运行流程:
- (A)用户打开客户端以后,客户端要求用户给予授权。
- (B)用户同意给予客户端授权。
- (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
- (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
- (E)客户端使用令牌,向资源服务器申请获取资源。
- (F)资源服务器确认令牌无误,同意向客户端开放资源
(B) 是关键,即用户如何给客户端进行授权。有了授权之,客户端就可以获取令牌,进而凭令牌获取资源。
1.4 OAuth 2.0 授权模式
客户端必须得到用户的授权(Authorization Grant),才能获得访问令牌(Access Token)。
- 授权码模式(Authorization Code)
- 密码模式(Resource Owner Password Credentials)
- 简化模式(Implicit)
- 客户端模式(Client Credentials)
其中,密码模式和授权码模式比较常用。
2 密码模式
代码语言:txt复制授权服务器:learn-authorization-server-password
资源服务器:learn-resource-server
密码模式,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向授权服务器索要授权。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而授权服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
- (A)用户向客户端提供用户名和密码。
- (B)客户端将用户名和密码发给授权服务器,向后者请求令牌。
- (C)授权服务器确认无误后,向客户端提供访问令牌。
2.1 搭建授权服务器
创建 learn-authorization-server-password 项目,搭建授权服务器。
2.1.1 引入依赖
代码语言:java复制<?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">
<parent>
<artifactId>learn-springsecurity-oauth-demo</artifactId>
<groupId>com.tostyle</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>learn-authorization-server-password</artifactId>
<dependencies>
<!-- 实现对 Spring MVC 的自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Spring Security OAuth2 的自动配置 -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${spring.boot.version}</version>
</dependency>
</dependencies>
</project>
添加 spring-security-oauth2-autoconfigure 依赖,引入 Spring Security OAuth 并实现自动配置。同时,它也引入了 Spring Security 依赖。
2.1.2 SecurityConfig
创建 SecurityConfig 配置类,提供一个账号密码为「tostyle/1024」的用户。代码如下:
代码语言:java复制package com.tostyle.authorization.password.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/**
* @author tostyle
* @date 2023-02-27 14:13
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.
// 使用内存中的 InMemoryUserDetailsManager
inMemoryAuthentication()
// 不使用 PasswordEncoder 密码编码器
.passwordEncoder(passwordEncoder())
// 配置 tostyle 用户
.withUser("tostyle").password("1024").roles("USER");
}
}
我们通过 Spring Security 提供认证功能,所以这里需要配置一个用户。
2.1.3 OAuth2AuthorizationServerConfig
创建 OAuth2AuthorizationServerConfig 配置类,进行授权服务器。代码如下: