Oauth2是个什么东西?

简介: 在之前的项目中只用到了SpringSecurity,后来发现公司的架构中有Oauth2,虽然自己在业务中没有过接触,但是觉得还是需要去了解一下,因此就有了这篇博客。本博客会从概念和简单的应用出发,讲解Oauth2的理论及实践,不涉及数据库等操作。

听说微信搜索《Java鱼仔》会变更强!


本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看


(一)前言


在之前的项目中只用到了SpringSecurity,后来发现公司的架构中有Oauth2,虽然自己在业务中没有过接触,但是觉得还是需要去了解一下,因此就有了这篇博客。本博客会从概念和简单的应用出发,讲解Oauth2的理论及实践,不涉及数据库等操作。


(二)什么是OAuth2


OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。


OAuth2协议包含几种角色:Client(客户端)、Resource Owner(资源拥有者)、Authorization Server(认证服务器)、Resource Server(资源服务器)。


网络异常,图片无法展示
|


上面这副图很详细地描述了OAuth2协议的运行原理:


A:用户打开一个客户端,客户端发送请求给资源的拥有者


B:资源拥有者返回一个需要授权的结果


C:用户在客户端上进行授权,授权信息发送到认证服务器


D:认证服务器认证完成后返回令牌


E:客户端通过令牌去访问资源服务器


F:资源服务器返回相应的资源、

以某个网站使用微信第三方登陆为例:


A:用户通过客户端打开某网站


B:某网站返回需要第三方登陆的信息


C:用户通过扫码在客户端同意登陆


D:认证服务器返回登陆成功后的token给客户端


E:客户端拿着token访问资源服务器


F:资源服务器接收token返回相应的资源


(三)OAuth2的应用场景


微信第三方就是OAuth2的应用场景之一。


我们在使用微信第三方登陆时,都需要先向微信申请到AppID和AppKey,然后拿着id和key去调用授权接口。


一般情况下大部分公司会将Oauth2应用在统一的认证中心,供第三方服务去访问他们的某些资源。


网络异常,图片无法展示
|


(四)OAuth2协议的四种模式


4.1 授权码模式 authorization_code


最常用的模式,也是上面所讲的模式,根据请求获取token,用token来访问资源。因为不涉及用户名和密码的泄漏,因此更加安全。


4.2 密码形式  password


传递用户名和密码的方式,不安全。


4.3 简化模式 implicit


不通过授权码,直接向认证系统要token。用到的场景很少。


4.4 客户端模式 client_credentials


客户端通过自己的名义向认证服务器获取授权,这种场景也很少见,比如一台只有一台硬件可以访问某个系统,可以理解为客户端模式。


(五)OAuth2认证服务器的实现


OAuth2只是一种协议,spring-security-oauth2是该协议的一种实现方式。接下来就通过spring-security-oauth2来实现认证授权。


5.1 引入依赖


首先引入项目中必要的依赖包


<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.security.oauth</groupId><artifactId>spring-security-oauth2</artifactId><version>2.1.5.RELEASE</version></dependency>

5.2 SpringSecurity配置


如果使用spring-security-oauth2,在获取oauth2的授权之前,必须要先获取SpringSecurity的授权,因此我们先配置SpringSecurity:


@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth) throwsException {
auth.inMemoryAuthentication()
                .passwordEncoder(newBCryptPasswordEncoder())
                .withUser("root")
                .password(newBCryptPasswordEncoder().encode("123456"))
                .authorities("/*");
    }
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                .csrf().disable();
    }
}


以上是最基本的SpringSecurity配置类,通过内存中设定的用户名root和密码123456进行登陆。


5.3 OAuth授权配置


AuthorizationServer配置的是一个认证服务器,当传入的条件满足配置时,就会在回调接口中带上对应的code值。下面的代码中主要配置了几个重要的参数,已经写在注释中。


@Component@EnableAuthorizationServerpublicclassAuthorizationConfigextendsAuthorizationServerConfigurerAdapter{
@AutowiredprivateBCryptPasswordEncoderbCryptPasswordEncoder;
@Overridepublicvoidconfigure(AuthorizationServerSecurityConfigurersecurity) throwsException {
//开启允许表单认证security.allowFormAuthenticationForClients()
                .checkTokenAccess("permitAll()");
    }
@Overridepublicvoidconfigure(ClientDetailsServiceConfigurerclients) throwsException {
clients.inMemory()
//client_id                .withClient("javayz")
//secret                .secret(bCryptPasswordEncoder.encode("my_secret"))
//授权模式                .authorizedGrantTypes("authorization_code")
//作用域,也就是权限范围                .scopes("all")
//资源的ID                .resourceIds("my_resource")
//回调地址                .redirectUris("http://localhost:8080/callback");
    }
@BeanpublicBCryptPasswordEncoderbCryptPasswordEncoder(){
returnnewBCryptPasswordEncoder();
    }
}

5.4 获取token方式


首先第一步,访问认证接口:


http://localhost:8080/oauth/authorize?client_id=javayz&response_type=code


第一次访问时,由于SpringSecurity的拦截,需要输入用户名和密码,我这里由于都是写在内存中的,因此输入root和123456即可。


网络异常,图片无法展示
|


输入用户名和密码之后,oauth会让你选择是否授权,这一步可以理解为微信第三方登陆时,微信扫码后在手机上点击授权。


授权成功之后,会跳转到回调接口中,并且带上一个code值。


http://localhost:8080/callback?code=KGNujV


接着我们要拿上这些code值去获取token:


网络异常,图片无法展示
|


当所有的参数都填写正确的情况下,就可以拿到access_token


由于在上面的代码中,我们开启了允许表单认证,因此可以通过接口判断token是否有效:


网络异常,图片无法展示
|


(六)Oauth2资源服务器的实现


写了认证后就需要写一个资源服务器进行验证,新建一个资源项目,启动的端口要和认证服务不同,编写资源服务器配置类:


@Configuration@EnableResourceServerpublicclassResourceConfigextendsResourceServerConfigurerAdapter {
privatestaticStringClientId="javayz";
privatestaticStringSecurity="my_secret";
@AutowiredprivateBCryptPasswordEncoderbCryptPasswordEncoder;
//token校验@BeanpublicRemoteTokenServicesremoteTokenServices(){
RemoteTokenServicestokenServices=newRemoteTokenServices();
tokenServices.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
tokenServices.setClientId(ClientId);
tokenServices.setClientSecret(Security);
returntokenServices;
    }
@Overridepublicvoidconfigure(HttpSecurityhttp) throwsException {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
http.authorizeRequests().anyRequest().authenticated();
    }
@Overridepublicvoidconfigure(ResourceServerSecurityConfigurerresources) throwsException {
resources.resourceId("my_resource").stateless(true);
    }
@BeanpublicBCryptPasswordEncoderbCryptPasswordEncoder(){
returnnewBCryptPasswordEncoder();
    }
}

这段代码的核心是remoteTokenServices,这里需要定义token校验的地址,以及对应的client和secret。


接着写一个接口用来测试:

@RestControllerpublicclassTestController {
@GetMapping("/test")
publicStringtest(){
return"测试接口";
    }
}

由于在配置类中设置了所有请求都需要认证,所以当我们直接访问时,会提示无权限:


网络异常,图片无法展示
|


这个时候需要将上面生成的token放入认证信息中,有两种方式,第一种是Postman在Authorization中设置Bearer token


网络异常,图片无法展示
|


第二种方式是在请求头header中设置认证,注意token的前缀


网络异常,图片无法展示
|


(七)总结


通过这篇博客,你应该知道了Oauth2是个什么东西,也可以在项目自己的项目中尝试着用一下。如果是公司层面的使用,还需要考虑其他的一些问题,比如用户信息的存储方式,token的生成方式等等。我是鱼仔,我们下期再见!



相关文章
|
消息中间件 SQL 存储
超详细的RabbitMQ入门,看这篇就够了!
RabbitMQ入门,看这篇就够了
219311 69
|
存储 缓存 监控
【JVM调优】如何进行JVM调优?一篇文章就够了!
深入解读JVM性能的监控、定位和调优方案,阐述jps/stat/jstack、MAT等常用性能分析工具的使用,提出JVM参数、内存溢出、内存泄漏、CPU飙升、GC频繁等实际场景下JVM调优的方案。
【JVM调优】如何进行JVM调优?一篇文章就够了!
|
7月前
|
设计模式 消息中间件 Java
【设计模式】【行为型模式】命令模式(Command)
一、入门 什么是命令模式? 命令模式是一种行为设计模式,它将请求或操作封装为对象,从而使你可以用不同的请求对客户进行参数化,并支持请求的排队、记录、撤销等操作。 命令模式的核心是将“请求”封装为独立的
228 15
|
9月前
|
人工智能 自然语言处理 安全
详解:Claude 3.7 Sonnet 国内使用指南_claude使用教程
Claude 3.7在对话理解和生成能力上都进行了显著的提升
6120 14
|
9月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——处理系统异常
本文介绍了在Spring Boot项目中如何通过创建`GlobalExceptionHandler`类来全局处理系统异常。通过使用`@ControllerAdvice`注解,可以拦截项目中的各种异常,并结合`@ExceptionHandler`注解针对特定异常(如参数缺失、空指针等)进行定制化处理。文中详细展示了处理参数缺失异常和空指针异常的示例代码,并说明了通过拦截`Exception`父类实现统一异常处理的方法。虽然拦截`Exception`可一劳永逸,但为便于问题排查,建议优先处理常见异常,最后再兜底处理未知异常,确保返回给调用方的信息友好且明确。
1205 0
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——处理系统异常
|
11月前
|
算法 Java 程序员
菜鸟之路Day06一一Java常用API
《菜鸟之路Day06——Java常用API》由blue编写,发布于2025年1月24日。本文详细介绍了Java中常用的API,包括JDK7的时间类(Date、SimpleDateFormat、Calendar)和JDK8新增的时间API(ZoneId、Instant、DateTimeFormatter等),以及包装类的使用。通过多个实例练习,如时间计算、字符串转整数、十进制转二进制等,帮助读者巩固所学内容,提升编程技能。文章强调了理论与实践结合的重要性,鼓励读者多做练习以提高学习效率。
197 28
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
28389 0
|
安全 Java 关系型数据库
单例模式下引发的线程安全问题
单例模式确保类在进程中仅有一个实例,适用于如数据库连接等场景。分为饿汉式与懒汉式:饿汉式在类加载时创建实例,简单但可能浪费资源;懒汉式延迟创建实例,需注意线程安全问题,常采用双重检查锁定(Double-Checked Locking)模式,并使用 `volatile` 关键字避免指令重排序导致的问题。
230 2
单例模式下引发的线程安全问题
|
设计模式 XML 存储
【七】设计模式~~~结构型模式~~~桥接模式(Java)
文章详细介绍了桥接模式(Bridge Pattern),这是一种对象结构型模式,用于将抽象部分与实现部分分离,使它们可以独立地变化。通过实际的软件开发案例,如跨平台视频播放器的设计,文章阐述了桥接模式的动机、定义、结构、优点、缺点以及适用场景,并提供了完整的代码实现和测试结果。桥接模式适用于存在两个独立变化维度的系统,可以提高系统的可扩展性和灵活性。
【七】设计模式~~~结构型模式~~~桥接模式(Java)
|
存储 Java
String 底层是如何实现的?
本文介绍了String类在Java中的底层实现,说明在JDK9之前String是基于`char[]`字符数组实现的,而JDK9及之后版本则使用`byte[]`字节数组实现,这种改变使得存储英文字符时空间效率提高,同时解释了字符串常量池的存储位置随JDK版本的演变。
270 0
String 底层是如何实现的?