OAuth 2.0

简介

OAuth 是一种开放标准的授权协议或框架,它提供了一种安全的方式,使第三方应用程序能够访问用户在其他服务上的受保护资源,而无需共享用户的凭证(如用户名和密码)。OAuth 的核心思想是通过“授权令牌”来代替直接使用用户名和密码进行身份验证。OAuth 不是属于任何一家公司的产品或服务。OAuth 是一个开放标准的授权框架,它由互联网工程任务组(IETF)定义,并通过社区贡献不断发展和完善。
OAuth 的开发和维护是由多个组织和个人共同参与的,不是由单一公司控制或拥有的。因此,它被广泛应用于各种互联网服务中,包括但不限于Google、Facebook、Twitter、Microsoft等大公司提供的服务。这些公司实现了OAuth协议来支持第三方应用的安全授权流程。
OAuth 名字里面的O代表Open,名字里的Auth是 “Authentication”(身份验证)或 “Authorization”(授权)的缩写。OAuth 的全称可以理解为 Open Authorization 或 Open Authentication,
主要特点

  • 安全性:避免了直接暴露用户的敏感信息,减少了潜在的安全风险。
  • 灵活性:支持多种授权模式,适用于不同的应用场景。
  • 广泛适用性:被众多互联网服务提供商采用,如WeiChat、Google、Facebook、Twitter等。

OAuth 1.0 和 OAuth 2.0 的区别

OAuth 1.0 和 OAuth 2.0 是两种不同的授权协议版本,虽然它们的目标都是为了安全地授权第三方应用访问用户资源,但在设计和实现上有显著差异。以下是两者的主要区别:

  1.  签名机制
    - OAuth 1.0:
      - 使用复杂的签名算法(如 HMAC-SHA1 或 RSA-SHA1)对每个请求进行签名。
      - 需要在每次请求中包含签名参数,增加了开发和调试的复杂性。
    - OAuth 2.0:
      - 不再强制要求对每个请求进行签名,而是依赖于传输层安全(TLS/SSL)来保护通信。
      - 简化了客户端的实现,减少了出错的可能性。
  2. 授权类型
    - OAuth 1.0:
      - 主要支持“三腿”(Three-legged)授权流程,即涉及客户端、用户和授权服务器。
    - OAuth 2.0:
      - 支持多种授权类型,包括但不限于:
        - 授权码模式(Authorization Code):适用于Web应用程序。
        - 隐式模式(Implicit):适用于浏览器或移动应用等无法安全存储密钥的客户端。
        - 密码模式(Resource Owner Password Credentials):适用于信任度高的客户端。
        - 客户端凭证模式(Client Credentials):适用于客户端直接访问资源而无需用户参与的场景。
  3. 令牌类型
    - OAuth 1.0:
      - 使用临时令牌(Request Token)和访问令牌(Access Token),需要额外的步骤来交换临时令牌为访问令牌。
      
    - OAuth 2.0:
      - 直接使用访问令牌(Access Token),简化了流程。
      - 引入了刷新令牌(Refresh Token),允许在访问令牌过期后获取新的访问令牌,而不需要再次让用户授权。
  4. 安全性
    - OAuth 1.0:
      - 依赖于签名机制来确保请求的完整性和真实性,但签名算法复杂且容易出错。
      
    - OAuth 2.0:
      - 更加依赖于HTTPS/TLS来保证通信的安全性,简化了安全配置。
      - 提供了更灵活的安全选项,例如通过短寿命的访问令牌和刷新令牌来增强安全性。
  5. 易用性和灵活性
    - OAuth 1.0:
      - 实现较为复杂,尤其是签名算法的处理,增加了开发和维护成本。
      
    - OAuth 2.0:
      - 设计更加简洁,易于实现和集成。
      - 提供了更多的灵活性,适用于各种类型的客户端和应用场景。
  6. 社区和支持
    - OAuth 1.0:
      - 已经逐渐被弃用,社区支持较少。
      
    - OAuth 2.0:
      - 广泛采用,拥有活跃的社区和丰富的文档及工具支持。

 总结
OAuth 2.0 在多个方面进行了改进,简化了授权流程,增强了灵活性,并依赖现代的安全措施(如TLS)。因此,OAuth 2.0 成为了当前最常用的授权协议版本,广泛应用于各种Web和移动应用中。

OAuth 2.0 的主要角色

  •  资源所有者(Resource Owner):通常是用户,拥有受保护资源的人。
  • 客户端(Client):希望访问受保护资源的应用程序,或三方应用程序。
  • 授权服务器(Authorization Server):负责颁发访问令牌。
  • 资源服务器(Resource Server):存储受保护资源并根据访问令牌提供资源。 

OAuth 2.0授权时序图

OAuth 2.0的授权与身份验证

 1. 授权(Authorization)

 OAuth 2.0 提供了多种授权模式(Grant Types),每种模式适用于不同的应用场景。以下是常见的授权模式及其技术实现:

 1.1 授权码模式(Authorization Code Grant)

- 适用场景:Web应用、移动应用等需要高安全性且能够安全存储客户端密钥的应用。
- 技术实现:
  - 重定向URI(redirect_uri):用户授权后,授权服务器将用户重定向到指定的URL,并附带授权码。
  - 授权码(Authorization Code):临时代码,用于换取访问令牌。
  - 客户端凭证(Client Credentials):客户端ID和客户端密钥,用于验证客户端身份。
  - TLS/SSL:确保通信的安全性。

 1.2 隐式模式(Implicit Grant)

- 适用场景:浏览器应用、单页应用(SPA)等无法安全存储客户端密钥的应用。
- 技术实现:
  - 重定向URI(redirect_uri):用户授权后,授权服务器直接将访问令牌附加到重定向URI的片段标识符中。
  - 访问令牌(Access Token):直接返回给客户端应用,无需额外步骤。
  - TLS/SSL:确保通信的安全性。

 1.3 密码模式(Resource Owner Password Credentials Grant)

- 适用场景:信任度高的客户端应用,如第一方应用。
- 技术实现:
  - 用户名和密码:用户直接提供凭证给客户端应用。
  - 客户端凭证(Client Credentials):客户端ID和客户端密钥,用于验证客户端身份。
  - TLS/SSL:确保通信的安全性。

 1.4 客户端凭证模式(Client Credentials Grant)

- 适用场景:客户端直接访问资源而无需用户参与的场景,如服务到服务通信。
- 技术实现:
  - 客户端凭证(Client Credentials):客户端ID和客户端密钥,用于验证客户端身份。
  - TLS/SSL:确保通信的安全性。

同时如果当访问令牌过期时,客户端可以使用刷新令牌来请求新的访问令牌,而不需要用户重新进行身份验证。

2. 验证(Authentication and Validation)

 2.1 访问令牌验证(Access Token Validation)

- JWT格式的访问令牌:
  - 签名验证:使用公钥或对称密钥验证JWT的签名,确保令牌未被篡改。
  - 过期时间检查:验证'exp'(过期时间)声明,确保令牌仍在有效期内。
  - 受众检查:验证'aud'(受众)声明,确保令牌是发给当前应用的。
  - 签发者检查:验证'iss'(签发者)声明,确保令牌来自可信的授权服务器。

- 不透明的访问令牌:
  -  introspection 端点:通过调用授权服务器的'/token/introspect'端点,验证令牌的有效性和其他属性。

 2.2 ID Token 验证(仅限OpenID Connect)

- 签名验证:使用公钥或对称密钥验证JWT的签名,确保ID Token未被篡改。
- 过期时间检查:验证'exp'(过期时间)声明,确保ID Token仍在有效期内。
- 受众检查:验证'aud'(受众)声明,确保ID Token是发给当前应用的。
- 签发者检查:验证'iss'(签发者)声明,确保ID Token来自可信的授权服务器。
- nonce检查:验证'nonce'声明,确保ID Token与原始授权请求中的'nonce'参数匹配,防止重放攻击。
- at_hash检查:如果同时使用了访问令牌,验证'at_hash'声明以确保访问令牌和ID Token的一致性。

使用Spring搭建OAuth 2.0 服务

1.创建Spring项目

2. 添加OAuth2 依赖

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- Spring Security OAuth2 Authorization Server -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-authorization-server</artifactId>
        <version>0.2.3</version> <!-- 请使用最新版本 -->
    </dependency>

    <!-- Spring Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- H2 Database -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Spring Boot DevTools -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3. 配置数据库

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  h2:
    console:
      enabled: true
      path: /h2-console
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true

 4. 配置Spring Security

 创建一个配置类来设置Spring Security,包括用户认证和授权服务器配置。

4.1. 创建用户实体和仓库

首先,创建一个简单的用户实体和JPA仓库。
User.java  

package com.example.oauth2server.model;

import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.util.Collection;
import java.util.List;

@Entity
@Data
public class User implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return List.of(new SimpleGrantedAuthority("ROLE_USER"));
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

UserRepository.java

package com.example.oauth2server.repository;

import com.example.oauth2server.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}
4.2. 配置用户认证

创建一个配置类来设置用户认证。
SecurityConfig.java 

package com.example.oauth2server.config;

import com.example.oauth2server.model.User;
import com.example.oauth2server.repository.UserRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class SecurityConfig {

    private final UserRepository userRepository;

    public SecurityConfig(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return username -> userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
 4.3. 配置授权服务器

创建一个配置类来设置授权服务器。
AuthorizationServerConfig.java

package com.example.oauth2server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

@Configuration
@EnableAuthorizationServer
@Order(1)
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private final PasswordEncoder passwordEncoder;

    public AuthorizationServerConfig(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

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

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore());
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Override
    public void configure(org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client")
                .secret(passwordEncoder.encode("secret"))
                .authorizedGrantTypes("authorization_code", "refresh_token", "password")
                .scopes("read", "write")
                .redirectUris("http://localhost:8080/callback")
                .accessTokenValiditySeconds(3600)
                .refreshTokenValiditySeconds(2592000);
    }
}
4.4. 配置资源服务器

 创建一个配置类来设置资源服务器。
ResourceServerConfig.java

package com.example.oauth2server.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/oauth/**").permitAll()
            .anyRequest().authenticated();
    }
}
4.5. 创建控制器
package com.example.oauth2server.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/getAuth")
    public String hello() {
        return xxxx.xxx();
    }
}
 4.6. 初始化数据
package com.example.oauth2server.config;

import com.example.oauth2server.model.User;
import com.example.oauth2server.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class DataLoader {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean
    public CommandLineRunner dataLoader() {
        return args -> {
            if (userRepository.findByUsername("user") == null) {
                User user = new User();
                user.setUsername("user");
                user.setPassword(passwordEncoder.encode("password"));
                userRepository.save(user);
            }
        };
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942370.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

玩原神学编程-原神时钟

前言 最近喜欢玩原神这种开放世界探索的游戏&#xff08;还有黑神话、古墓丽影等&#xff09;&#xff0c;只能说纳塔版本的boss盾真的厚&#xff0c;萌新的我去打boss&#xff0c;从白天打到黑夜&#xff0c;黑夜再打到白天&#xff08;游戏里面的时间&#xff09;。 闲话结…

【Spring】深入解析 Spring 原理:Bean 的多方面剖析(源码阅读)

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 一、Bean的作用域 在 Java Spring 框架中&#xff0c;Bean 的作用域是一个关键概念&#xff0c;它决定了 Bean 的生命周期和实例化方式&#xff0c;对应用的性…

基于高德地图js api实现掩膜效果 中间矢量 周围卫星图

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>管网服务</title><style>html,body,#ma…

Vue.js组件(6):echarts组件

1 前言 本章主要对常用的echars图表展示进行基本的组件封装。使用该组件前需要在项目中引入echarts。官网&#xff1a;Apache ECharts npm install echarts --save 2 图表组件 2.1 折线图组件 组件属性&#xff1a;chartId&#xff0c;指定图表挂载div的id&#xff0c;注意不…

RCE常见姿势

文章目录 常见漏洞执行函数&#xff1a;1.系统命令执行函数2.代码执行函数 命令拼接符读取文件命令绕过&#xff1a;空格过滤绕过关键字绕过长度过滤绕过无参数命令执行绕过无字母数字绕过利用%0A截断利用回溯绕过利用create_function()代码注入无回显RCE1.反弹shell2.dnslog外…

selenium执行js

JS知识 获取元素 document.getElement 移除属性&#xff1a;removeAttribute("xx") 窗口移动&#xff1a;window.scrollTo(0, document.body.scrollHeight)方法 drivier.execute_script(js)场景&#xff1a; 日期选择框&#xff0c;不能输入&#xff0c;只能设置…

三维场景重建与3D高斯点渲染技术探讨

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月25日10点11分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 文章源地址(有视频)&#xff1a;链接h…

springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失

这个包丢失了 启动不了 起因是pom中加入了 <tomcat.version></tomcat.version>版本指定&#xff0c;然后idea自动编译后&#xff0c;包丢了&#xff0c;删除这个配置后再也找不回来&#xff0c; 这个包正常在 <dependency><groupId>org.springframe…

Java日志框架:log4j、log4j2、logback

文章目录 配置文件相关1. properties测试 2. XMl使用Dom4j解析XML Log4j与Log4j2日志门面 一、Log4j1.1 Logges1.2 Appenders1.3 Layouts1.4 使用1.5 配置文件详解1.5.1 配置根目录1.5.2 配置日志信息输出目的地Appender1.5.3 输出格式设置 二、Log4j22.1 XML配置文件解析2.2 使…

基于LSTM长短期记忆神经网络的多分类预测【MATLAB】

在深度学习中&#xff0c;长短期记忆网络&#xff08;LSTM, Long Short-Term Memory&#xff09;是一种强大的循环神经网络&#xff08;RNN&#xff09;变体&#xff0c;专门为解决序列数据中的长距离依赖问题而设计。LSTM因其强大的记忆能力&#xff0c;广泛应用于自然语言处理…

机器学习基础 衡量模型性能指标

目录 1 前言 ​编辑1.1 错误率(Error rate)&精度(Accuracy)&误差(Error)&#xff1a; 1.2 过拟合(overfitting): 训练误差小&#xff0c;测试误差大 1.3 欠拟合(underfitting)&#xff1a;训练误差大&#xff0c;测试误差大 1.4 MSE: 1.5 RMSE: 1.6 MAE: 1.7 R-S…

TCP的流量控制的实现

滑动窗口的介绍 滑动窗口是tcp协议中的一个重要概念&#xff0c;滑动窗口是字节为单位&#xff0c;而tcp头部的序列化和确认号也是以字节为单位的&#xff0c;滑动窗口里是含有可以传输的字节的数量&#xff08;可以传输不是已经传输&#xff09;&#xff0c;而滑动窗口的大小是…

【0x001D】HCI_Read_Remote_Version_Information命令详解

目录 一、命令概述 二、命令格式及参数说明 2.12. HCI_Read_Remote_Version_Information 命令格式 2.2. Connection_Handle 三、生成事件 3.1. HCI_Command_Status 事件 3.2. HCI_Read_Remote_Version_Information_Complete 事件 四、命令执行流程 4.1. 命令发起阶段(…

一篇文章学会HTML

目录 页面结构 网页基本标签 图像标签 超链接标签 文本链接 图像链接 锚链接 功能链接 列表 有序列表 无序列表 自定义列表 表格 跨列/跨行 表头 媒体元素 视频 音频 网站的嵌套 表单 表单元素 文本框 单选框 多选框 按钮 下拉框 文本域和文件域 表…

C语言项目 天天酷跑(上篇)

前言 这里讲述这个天天酷跑是怎么实现的&#xff0c;我会在天天酷跑的下篇添加源代码&#xff0c;这里会讲述天天酷跑这个项目是如何实现的每一个思路&#xff0c;都是作者自己学习于别人的代码而创作的项目和思路&#xff0c;这个代码和网上有些许不一样&#xff0c;因为掺杂了…

如何完全剔除对Eureka的依赖,报错Cannot execute request on any known server

【现象】 程序运行报错如下&#xff1a; com.netflix.discovery.shared.transport.TransportException报错Cannot execute request on any known server 【解决方案】 &#xff08;1&#xff09;在Maven工程中的pom去掉Eureka相关的引用&#xff08;注释以下部分&#xff0…

华为云国内版与国际版的主要区别解析

华为云作为全球领先的云计算服务提供商&#xff0c;提供了国内版和国际版两种服务。虽然它们都旨在为用户提供高效、可靠的云计算解决方案&#xff0c;但在功能、服务、合规性等方面存在一些显著的区别。我们九河云通过本文将详细分析华为云国内版与国际版的主要区别&#xff0…

基于北斗短报文+4G的森林草原火险因子综合监测方案

近年来&#xff0c;全球气候变暖的趋势日益严重&#xff0c;气温升高导致森林火灾的发生频率和严重程度逐年增加&#xff0c;对人类社会和自然生态环境造成了严重的危害。森林火灾的发生受到植被类型、气象条件、扑救方式和监管方式等多种因素的影响。 因此&#xff0c;林业建…

小程序app封装公用顶部筛选区uv-drop-down

参考ui:DropDown 下拉筛选 | 我的资料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生态框架 样式示例&#xff1a; 封装公用文件代码 dropDownTemplete <template><!-- 顶部下拉筛选区封装公用组件 --><view><uv-drop-down ref&…

3 JDK 常见的包和BIO,NIO,AIO

JDK常见的包 java.lang:系统基础类 java.io:文件操作相关类&#xff0c;比如文件操作 java.nio:为了完善io包中的功能&#xff0c;提高io性能而写的一个新包 java.net:网络相关的包 java.util:java辅助类&#xff0c;特别是集合类 java.sql:数据库操作类 IO流 按照流的流向分…