OAuth2.0客户端和服务端Java实现

2024-04-09 08:04

本文主要是介绍OAuth2.0客户端和服务端Java实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

oauth2

引言

读了《设计模式之美》和《凤凰架构》架构安全篇之后,决定写一个OAuth2.0的认证流程的Demo,也算是一个阶段性的总结,具体原理实现见《凤凰架构》(架构安全设计篇)。

涉及到的源码可以从https://github.com/WeiXiao-Hyy/oauth2获取,欢迎Star!

OAuth2.0原理

主要解决的问题

面向解决第三方应用(Third-Party Application)的认证授权协议,使用Token代替用户密码作为授权的凭证。

  1. 有了令牌之后,哪怕令牌被泄漏,也不会导致密码的泄漏
  2. 令牌上可以设定访问资源的范围以及时效性
  3. 每个应用都持有独立的令牌,哪个失效都不会波及其他

OAuth2.0一共提出了四种不同的授权方式:

  • 授权码模式(Authorization Code)
  • 隐式授权模式(Implicit)
  • 密码模式(Resource Owner Password Credentials)
  • 客户端模式(Client Credentials)

本文介绍和实现的是授权码方式。

OAuth2.0流程图

  1. client请求授权服务端,获取Authorization Code;
  2. client通过Authorization Code再次请求授权服务端,获取Access Token;
  3. client通过服务端返回的Access Token获取用户的基本信息。

流程图如下所示:

请添加图片描述

第一次使用github账号应用来登陆掘金,需要进行授权

掘金即是第三方应用, 请求GitHub。

请添加图片描述

注册一个新的OAuth Application

如果我们需要使用GitHub账号来关联我们自己的第三方应用则需要完整走一遍OAuth2.0流程。

请添加图片描述

GitHub生成的client_id, client_secret(密钥), redirect_uri, homepage_url, application_name等等。

请添加图片描述

clientId如何生成唯一的

在注册clientId以及申请clientSecret时,如何保证生成的clientId是不重复的呢?

和JWT以及Cookie-Session对比

参考《凤凰架构》架构安全篇 https://icyfenix.cn/architect-perspective/general-architecture/system-security/authorization.html

谈谈State参数为什么可以防止CSRF攻击

观察GitHub OAuth2.0实现文档,可以观察到在authroize接口需要传递一个state参数,并且在redirect_uri重定向时原封不动传递回来,所以为什么可以防止CSRF攻击呢?

请添加图片描述

核心: 在于授权服务端进行token请求绑定时,会从session将本次会话的账号与生成access_token进行绑定,而对于用户是谁并不关心。

案例
请添加图片描述

  1. 用户B登录掘金网站,并且选择绑定自己的GitHub账号;
  2. 掘金网站将用户B重定向到GitHub,由于他之前已经登录过GitHub,所以GitHub直接向他显示是否授权掘金访问的页面;
  3. 用户B在点击"同意授权"之后,截获GitHub服务器返回的含有authorization code参数的HTTP响应;
  4. 用户B精心构造一个Web页面,它会触发掘金网站向GitHub发起令牌申请的请求,而这个请求中的authorization code
    参数正是上一步截获到的code;
  5. 用户B将这个Web页面放到互联网上,等待或者诱骗受害者用户A来访问;
  6. 用户A之前登录了掘金
    网站,只是没有把自己的账号和其他社交账号绑定起来。在用户A访问了用户B准备的这个Web页面,令牌申请流程在用户A的浏览器里被顺利触发,掘金
    网站从GitHub那里获取到access_token,但是这个token以及通过它进一步获取到的用户信息却都是攻击者用户B;
  7. 掘金网站将用户B的GitHub账号同用户A的掘金账号关联绑定起来,从此以后,用户B就可以用自己的GitHub账号通过OAuth
    登录到用户A在掘金网站中的账号,堂而皇之的冒充用户A的身份执行各种操作;

代码实现(知识碎片总结)

本部分将开发过程中遇到的难点记录下来,具体源码参考此repo 👍

postman 请求共享session问题

本文为单体应用,使用了HttpServletRequestHttpSession方便开发,将相关的数据保存在服务器的Session中,但是Postman在发送请求的时候,
不会将其视为同一个连接,导致获取不到Session中的数据,需要每次将用户登陆的Cookie赋值到相应的接口上才能获取到Session中的数据。

请添加图片描述

实现HandlerInterceptor接口完成请求过滤

涉及到接口请求过滤条件时,可以通过实现WebMvcConfigurer接口来添加过滤规则,例如:

  1. 授权前用户没有登陆则需要重定向到登陆页面
  2. 如果access_token过期,则需要重新获取
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {//注意注入bean的写法@Beanpublic OauthInterceptor oauthInterceptor() {return new OauthInterceptor();}@Beanpublic AuthAccessTokenInterceptor accessTokenInterceptor() {return new AuthAccessTokenInterceptor();}@Beanpublic LoginInterceptor loginInterceptor() {return new LoginInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor()).addPathPatterns("/user/**", "/oauth2.0/authorizePage", "/oauth2.0/authorize", "/sso/token");registry.addInterceptor(oauthInterceptor()).addPathPatterns("/oauth2.0/authorize");registry.addInterceptor(accessTokenInterceptor()).addPathPatterns("/api/**");}
}

参考资料

  • https://icyfenix.cn/architect-perspective/general-architecture/system-security/
  • https://time.geekbang.org/column/intro/100039001
  • https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
  • https://juejin.cn/post/6844903668861534215#heading-4
  • https://www.jianshu.com/p/c7c8f51713b6

这篇关于OAuth2.0客户端和服务端Java实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/887608

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听