Spring Security、oauth2、单点登陆SSO的关系

您所在的位置:网站首页 sso登录异常什么意思啊 Spring Security、oauth2、单点登陆SSO的关系

Spring Security、oauth2、单点登陆SSO的关系

2024-07-05 09:25| 来源: 网络整理| 查看: 265

文章目录 概述1. 什么是Spring Security1.1 配置示例1.2 spring security 基本原理1.2 Spring Security存在的问题 2. 什么是oauth22.1 那么如何实现检查token的呢2.2 jwt2.3 endpoint概念2.4 spring Security和 spring Security oauth2关系 3. spring cloud oauth24. sso单点登陆5. 统一网关

概述

网上有很多Spring Security和 oauth2的介绍,但是对于初学者来说,上手比较复杂,本篇从原理上梳理一下两者之间的联系和区别

1. 什么是Spring Security

参见 【Spring Security】基本功能介绍

spring security 的核心功能主要包括:

认证 (你是谁) 通过注解 @EnableWebSecurity开启

简单来说,就是需要登录,你需要输入用户名和密码,才能访问某个url。

授权 (你能干什么) 不需要通过指定的开关开启,而是通过配置来增加授权规则来生效,不增加授权规则就不生效

授权的目的是可以把资源进行划分,例如公司有不同的资料,有普通级别和机密级别,只有公司高层才能看到机密级别的子类,而普通级别的资料大家都可以看到! 那么授权就是允许你查看某个资源,当然,如果你没有权限,就拒绝你查看!

授权有个前提就是先认证才能授权,例如你是A公司的人,有A公司的卡牌,才能进入A公司资料库。如果是B公司的人,大门都不给你进。

认证可以单独使用,即不划分资源的级别,所有人只要登录都可以查看

1.1 配置示例 public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { //配置安全拦截策略 @Override protected void configure(HttpSecurity http) throws Exception { //链式配置拦截策略 http .csrf().disable()//关闭csrg跨域检查 //这里注意matchere是有顺序的。 .authorizeRequests() .antMatchers("/user/**").hasAuthority("user") .antMatchers("/order/**").hasAuthority("order") .antMatchers("/common/**").permitAll() //common下的请求直接通过 .antMatchers("/**.html","/js/**","/css/**","/img/**").permitAll()//放行静态资源 .anyRequest().authenticated() //其他请求需要登录 .and()//并行条件 .formLogin() .loginPage("/index.html")//自定义登录页面 .loginProcessingUrl("") .defaultSuccessUrl("/main.html").failureUrl("/common/loginFailed"); //可从默认的login页面登录,并且登录后跳转到main.html }

简单来说:

配置了 @EnableWebSecurity,就需要先登陆, .anyRequest().authenticated() 就是让你登陆的意思系统内置了登陆页面,一般情况下都是需要定制的,因此,通过 .loginPage(“/index.html”) 你可以指定自定义的登陆页由于有些资源是不需要登陆就行访问的,例如登陆页html,否则,形成死循环了。index.html等价于售票处,你总得让游客免票入内吧.antMatchers(“/user/**”).hasAuthority(“user”)用于定制哪些请求有额外要求,例如景区内的厕所,先买大门票后,男的进男侧,不允许进女厕 1.2 spring security 基本原理

spring security的核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是 Basic Authentication Filter 用来认证用户的身份,一个在spring security中一种过滤器处理一种认证方式。

如下图所示,这是一组链式处理器类,请求从做往右依次经过多个过滤器类处理:

在这里插入图片描述

比如,对于username password认证过滤器来说:

会检查是否是一个登录请求; 是否包含username 和 password (也就是该过滤器需要的一些认证信息) ; 如果不满足则放行给下一个。

下一个按照自身职责判定是否是自身需要的信息,basic的特征就是在请求头中有 Authorization:Basic eHh4Onh4 的信息。中间可能还有更多的认证过滤器。最后一环是 FilterSecurityInterceptor,这里会判定该请求是否能进行访问rest服务,判断的依据是 BrowserSecurityConfig中的配置,如果被拒绝了就会抛出不同的异常(根据具体的原因)。Exception Translation Filter 会捕获抛出的错误,然后根据不同的认证方式进行信息的返回提示。

注意:绿色的过滤器可以配置是否生效,其他的都不能控制。

1.2 Spring Security存在的问题

一般情况下 ,Spring Security 应用在一个单体项目中,此时只存在一个独立的项目,你访问一个资源,需要输入用户名和密码就行了

在多体应用中,特别是存在第三方的场景下,我们存在这样的需求:

假设你去注册csdn的账户,那么需要填入手机号、昵称、邮箱等信息,有的繁琐,如果你已经有了微信账户的话,那么csdn可以从微信处获取这些信息,而你只需要通过手机扫一下就实现了,是不是很方便?oauth2协议应运而生。你去访问csdn注册页面,然后页面转向微信登陆页面(授权中心角色),你输入正确的用户名和密码(手机扫码是输入用户名和密码的一种变形),然后csdn获得了token,带着token,访问微信的用户信息接口(资源中心角色),微信返回用户的邮箱等信息,csdn利用这些信息,完成注册新用户,入用户表

什么是单体应用?就是资源和检查权限的系统都正在一个地方,传统的注册csdn手动输入邮箱,然后你登陆csdn,就是单体应用,而我们去注册csdn,此时微信的个人信息数据就是第三方系统的,此时涉及csdn和微信2个系统

2. 什么是oauth2

此时一般的文章都是通过2个步骤来演示的,第一步 拿到token,通过浏览器发送一个请求,完成用户名密码登陆输入,模拟获取token过程,第二步 携带token获取资源,通过postman发送请求模拟查询资源

oauth2是一种协议,核心是用token令牌替换直接输入用户名和密码的方式,通过该协议,可以实现跨服务至之间的授权功能。一般分为2个模块,认证授权中心和资源中心,资源中心可以有多个:

授权中心:负责颁发token,配置`@EnableAuthorizationServer

资源中心:负责检查token(可以自己检查,例如jwt本地检查 或委托授权中心检查),检查通过后发放资源。

基础原理是这样的:

授权中心颁发token 这个没啥原理,就是让用户输入用户名和密码,检查下是否正确,然后返回一个token,说白了就是一个字符串,并存在授权中心的服务器上。

就像你买的饭票一样,你用现金买了饭票,将来凭借饭票就可以领取一份盒饭!不需要再付钱了

向资源中心发起一个资源的查询,资源中心检查token,检查通过后,发放资源。

关键点在于微信颁发的token,可以给csdn,csdn带着token去微信获取资源,这个步骤是在csdn后台完成的,对用户来说是隐藏的。也就是说csdn拿了饭票,去微信领盒饭了,不需要付钱(输入密码),爽!

OAuth是Open Authority的缩写,是令牌代替用户密码访问应用的又一标准, OAuth 协议存在第一代和第二代之分,后者称为OAuth2,Spring OAuth2是实现OAuth2协议的具体的框架之一,你也可以使用其他的OAuth2框架。

对于大家而言,我们在互联网应用中最常见的 OAuth2 应该就是各种第三方登录了。利用OAuth2协议,我们在注册csdn账户的时候,可以直接使用微信或QQ账户进行注册,这样,仅需登陆微信或QQ,即可让csdn获取到用户的昵称、爱好、邮箱等基础信息

2.1 那么如何实现检查token的呢

答案在于 @EnableResourceServer注解,表示开启资源中心功能,会有代理类负责登陆和授权的检查:

如果某个服务的入口类被 @EnableResourceServer注解,说明现在是基于oauth2协议的架构,那么原来的Spring Security配置会被覆盖: 在这里插入图片描述 一般的Spring Security要求所有的请求url都要先判断是否登录,如果没有登录,就跳转至登陆页,然后检查用户名和密码是否正确,但是资源中心注解会内置有更高优先级的拦截器,会修改这个默认的逻辑,不是通过用户名和密码来检查是否正确,而是通过检查消息头中的Authorization:Bearer xxx参数。

开启资源中心,所有资源优先用token方式进行检查,即检查消息头中是否含有 Authorization:Bearer xxx 这样格式的; 如果没有token,直接判定失败;即使有了token,那么如何验证?可以本地验证,或转发token至授权中心进行判断

授权中心颁发token后,会把token存储在内存中,这样当ABC服务获得token后,转发至授权中心,和内存中存储的原始值进行比较就行了。

2.2 jwt

token默认是明文的不安全,采用jwt,可以进行加密,更安全!

加密有2种形式:

对称加密

缺点:容易破解

非对称加密

优点:不容易破解

2.3 endpoint概念

授权中心需要配置endpoint,那么endpoint是什么?

授权中心内置一些url,表示用于token特定的功能,这些url是免密使用的:

授权中心内置很多url资源,例如/oauth/token,这些url就是endpoint概念

在这里插入图片描述

你可以去复写/oauth/token 这样的url

2.4 spring Security和 spring Security oauth2关系

从第一章节,我们知道, spring Security是一个框架,提供了认证和授权功能,从本章得知oauth2是一个协议,光有协议也没用,你的有具体的实现,那么spring Security oauth2是什么东西呢?答案就是 spring Security框架内置了oauth2的api,可以直接使用。当然,其他框架也有oauth2的实现,你可以根据需求选择。

3. spring cloud oauth2

我们在第二章节用到的语法,Spring Security的oauth2 是内置在Spring Security包中的,例如@EnableAuthorizationServer 开启授权中心注解是在spring-security-oauth2-2.3.4.RELEASE.jar,说明Spring Security框架已经包含了oauth2协议的api接口:

从注解的package 能看出是springframework下的,说明是基础包:

package org.springframework.security.oauth2.config.annotation.web.configuration; public @interface EnableAuthorizationServer { }

spring cloud oauth2是提供了一个starter,自动引入相关的依赖包,仅仅是方便使用,并没有新增特殊的功能:

org.springframework.cloud spring-cloud-starter-oauth2 4. sso单点登陆

通过前面的学习,我们知道,利用token原理,可以实现登陆一个系统后,只输入一次用户名和密码,然后在cookie中保存这个token,再访问其他系统时,带上这个token,就可以直接访问资源了。

oauth2的基本原理就是利用了token实现的,帮助我们利用第三方系统获得资源。

单点登录的英文名是 Single Sign On,因此一般简称为SSO。它的用途在于,不管多么复杂的应用群,只要在用户权限范围内,那么就可以做到,用户只需要登录一次就可以访问权限范围内的所有应用子系统。对于用户而言,访问多个应用子系统只需要登录一次,同样在需要注销的时候也只需要注销一次。举个简单的例子,你在百度首页登录成功之后,你再访问百度百科、百度知道、百度贴吧等网站也会处于登录状态了,这就是一个单点登录的真实案例。

划分为2类角色:

授权服务器 负责检查是否授权及生成token资源服务器,提供资源,如果发现没有登陆,统一重定向至授权中心进行token授权。多台资源服务器可以共享同一个token,不用每次都生成token

特点是 检查是否有权限的操作是在资源服务器上,即每个资源服务器都有检查的逻辑。

缺点:sso默认配置仅能解决登陆认证问题,但是解决不了授权问题,即/user 和/order需要不同的权限

单点登陆和Oauth2的区别和联系:

相似点都是利用token作为介质单点登陆侧重多个子系统的场景,登陆一个,另几个系统免登陆,简单来说就是同一个公司下的不同子系统,而oauth2侧重存在一个第三方系统,彼此完全独立,简单理解就是不同公司旗下的不同系统。单点登陆侧重认证,即检查是否登陆,一般不细分权限,即只要登陆即可,所有的功能都可以访问。如果有角色概念,那么单点登陆就不能完全满足,需要额外的工作去负责授权检查;oauth2侧重认证+授权,属于单一url的,一次只能访问特定的资源,如果访问多个资源,需要多个tokensso实际上是扩展了oauth2的功能,即扩展了oauth2协议的,使之用于某个特殊场景,即带有子系统的一个大系统!

也就是说不同公司之间的系统,采用oauth2就是完美方案! 如果是同一个公司的不同子系统,那么不考虑复杂的授权的场景下,单点登陆就是完美方案! 如果单点登陆同时需要考虑授权的情况,那么就要考虑授权功能,系统就更复杂了,需要sso+授权,例如下一章节就是该问题的解决方案!

5. 统一网关

从前面学习的示例来看,是不包含网关的,即sso项目是多个独立服务都要进行鉴权,每个服务都要配置一套鉴权系统,只不过是把具体的处理流程转发至同一个鉴权中心了,只要登录一次,就可以在多个服务中心共享登录信息。那么有了网关之后怎么办?

有了网关,可以在网关处进行鉴权,后续的请求转发至具体服务后,后者不再需要进行鉴权了,或者网关暂不处理鉴权,转发请求至具体的服务后,由服务自行进行鉴权

有了网关之后,就有了统一的入口!

如果项目集成了网关,在网关里整合 OAuth2.0,实现单点登陆 有两种思路:

一种是授权服务器生成令牌, 所有请求统一在网关层验证,判断权限等操作;

优点: 只有网关层一个模块负责检查权限,资源模块都不用涉及 缺点:需要改造,对技术要求高

另一种是由各资源服务处理,网关只做请求转发。 这种情况下,不用做特殊处理,等价于第四章节的sso单点登陆

优点:保留现有架构不动,每个资源服务配置sso即可 缺点:每个资源服务配置sso,架构上不好,存在冗余的感觉

比较常用的是第一种,把API网关作为OAuth2.0的资源服务器角色,实现接入客户端权限拦截、令牌解析并转发当前登录用户信息给微服务,这样下游微服务就不需要关心令牌格式解析以及OAuth2.0相关机制了。

网关在认证授权体系里主要负责两件事: (1)作为OAuth2.0的资源服务器角色,实现接入方权限拦截。 (2)令牌解析并转发当前登录用户信息(明文token)给微服务

微服务拿到明文token(明文token中包含登录用户的身份和权限信息)后也需要做两件事: (1)用户授权拦截(看当前用户是否有权访问该资源) (2)将用户信息存储进当前线程上下文(有利于后续业务逻辑随时获取当前用户信息)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3