SpringSecurityOAuth2.0认证授权

SpringSecurityOAuth2.0认证授权
1. 基本概念
1.1 什么是认证
  进⼊移动互联⽹时代,⼤家每天都在刷⼿机,常⽤的软件有、⽀付宝、头条等,下边拿来举例⼦说明认证相关的基本概念,在初次使⽤前需要注册成为⽤户,然后输⼊账号和密码即可登录,输⼊账号和密码登录的过程就是认证。
系统为什么要认证?
  认证是为了保护系统的隐私数据与资源,⽤户的⾝份合法⽅可访问该系统的资源。
认证:⽤户认证就是判断⼀个⽤户的⾝份是否合法的过程,⽤户去访问系统资源时系统要求验证⽤户的⾝份信息,⾝份合法⽅可继续访问,不合法则拒绝访问。常见的⽤户⾝份认证⽅式有:⽤户名密码登录,⼆维码登录,⼿机短信登录,指纹认证等⽅式。
1.2 什么是会话
  ⽤户认证通过后,为了避免⽤户的每次操作都进⾏认证可将⽤户的信息保证在会话中。会话就是系统为了保持当前⽤户的登录状态所提供的机制,常见的有基于session ⽅式、基于token⽅式等。
基于session的认证⽅式如下图:
  它的交互流程是,⽤户认证成功后,在服务端⽣成⽤户相关的数据保存在session(当前会话)中,发给客户端的sesssion_id 存放到 cookie 中,这样⽤户客户端请求时带上session_id 就可以验证服务器端是否存在 session 数据,以此完成⽤户的合法校验,当⽤户退出系统或session过期销毁时,客户端的session_id也就⽆效了。
基于token⽅式如下图:
  它的交互流程是,⽤户认证成功后,服务端⽣成⼀个token发给客户端,客户端可以放到 cookie 或 localStorage等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认⽤户⾝份。
基于session的认证⽅式由Servlet规范定制,服务端要存储session信息需要占⽤内存资源,客户端需要⽀持cookie;
基于token的⽅式则⼀般不需要服务端存储token,并且不限制客户端的存储⽅式。如今移动互联⽹时代更多类型的客户端需要接⼊系统,系统多是采⽤前后端分离的架构进⾏实现,所以基于token的⽅式
更适合。
1.3 什么是授权
  例如登录成功后⽤户即可使⽤的功能,⽐如,发红包、发朋友圈、添加好友等,没有绑定银⾏卡的⽤户是⽆法发送红包的,绑定银⾏卡的⽤户才可以发红包,发红包功能、发朋友圈功能都是的资源即功能资源,⽤户拥有发红包功能的权限才可以正常使⽤发送红包功能,拥有发朋友圈功能的权限才可以使⽤发朋友圈功能,这个根据⽤户的权限来控制⽤户使⽤资源的过程就是授权。
为什么要授权?
  认证是为了保证⽤户⾝份的合法性,授权则是为了更细粒度的对隐私数据进⾏划分,授权是在认证通过后发⽣的,控制不同的⽤户能够访问不同的资源。
授权:授权是⽤户认证通过根据⽤户的权限来控制⽤户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。
2. 分布式系统认证⽅案
2.1 什么是分布式系统
  随着软件环境和需求的变化,软件的架构由单体结构演变为分布式架构,具有分布式架构的系统叫分布式系统,分布式系统的运⾏通常依赖⽹络,它将单体结构的系统分为若⼲服务,服务之间通过⽹络交互来完成⽤户的业务处理,当前流⾏的微服务架构就是分布式系统架构,如下图:
分布式系统具体如下基本特点:
1、分布性:每个部分都可以独⽴部署,服务之间交互通过⽹络进⾏通信,⽐如:订单服务、商品服务。
2、伸缩性:每个部分都可以集⽅式部署,并可针对部分结点进⾏硬件及软件扩容,具有⼀定的伸缩能⼒。
3、共享性:每个部分都可以作为共享资源对外提供服务,多个部分可能有操作共享资源的情况。
4、开放性:每个部分根据需求都可以对外发布共享资源的访问接⼝,并可允许第三⽅系统访问。
2.2 分布式认证需求
  分布式系统的每个服务都会有认证、授权的需求,如果每个服务都实现⼀套认证授权逻辑会⾮常冗余,考虑分布式系统共享性的特点,需要由独⽴的认证服务处理系统认证授权的请求;考虑分布式系
统开放性的特点,不仅对系统内部服务提供认证,对第三⽅系统也要提供认证。分布式认证的需求总结如下:
(1)统⼀认证授权
  提供独⽴的认证服务,统⼀处理认证授权。⽆论是不同类型的⽤户,还是不同种类的客户端(web端,H5、APP),均采⽤⼀致的认证、权限、会话机制,实现统⼀认证授权。
要实现统⼀则认证⽅式必须可扩展,⽀持各种认证需求,⽐如:⽤户名密码认证、短信验证码、⼆维码、⼈脸识别等认证⽅式,并可以⾮常灵活的切换。
(2)应⽤接⼊认证
  应提供扩展和开放能⼒,提供安全的系统对接机制,并可开放部分API给接⼊第三⽅使⽤,⼀⽅应⽤(内部系统服务)和三⽅应⽤(第三⽅应⽤)均采⽤统⼀机制接⼊。
2.3 分布式认证⽅案
2.3.1 选型分析
1、基于session的认证⽅式
  在分布式的环境下,基于session的认证会出现⼀个问题,每个应⽤服务都需要在session中存储⽤户⾝份信息,通过负载均衡将本地的请求分配到另⼀个应⽤服务需要将session信息带过去,否则会重新认证。
这个时候,通常的做法有下⾯⼏种:
Session复制:多台应⽤服务器之间同步session,使session保持⼀致,对外透明。
Session黏贴:当⽤户访问集中某台服务器后,强制指定后续所有请求均落到此机器上。
Session集中存储:将Session存⼊分布式缓存中,所有服务器应⽤实例统⼀从分布式缓存中存取Session。
总体来讲,基于session认证的认证⽅式,可以更好的在服务端对会话进⾏控制,且安全性较⾼。但是,session机制⽅式基于cookie,在复杂多样的移动客户端上不能有效的使⽤,并且⽆法跨域,另外随着系统的扩展需提⾼session的复制、黏贴及存储的容错性。
2、基于token的认证⽅式
  基于token的认证⽅式,服务端不⽤存储认证数据,易维护扩展性强,客户端可以把token 存在任意地⽅,并且可以实现web和app统⼀认证机制。其缺点也很明
显,token由于⾃包含信息,因此⼀般数据量较⼤,⽽且每次请求都需要传递,因此⽐较占带宽。另外,token的签名验签操作也会给cpu带来额外的处理负担。
2.3.2 技术⽅案
  根据选型的分析,决定采⽤基于token的认证⽅式,它的优点是:
1、适合统⼀认证的机制,客户端、⼀⽅应⽤、三⽅应⽤都遵循⼀致的认证机制。
2、token认证⽅式对第三⽅应⽤接⼊更适合,因为它更开放,可使⽤当前有流⾏的开放协议Oauth2.0、JWT等。
3、⼀般情况服务端⽆需存储会话信息,减轻了服务端的压⼒。
分布式系统认证技术⽅案见下图:
流程描述:
(1)⽤户通过接⼊⽅(应⽤)登录,接⼊⽅采取OAuth2.0⽅式在统⼀认证服务(UAA)中认证。
(2)认证服务(UAA)调⽤验证该⽤户的⾝份是否合法,并获取⽤户权限信息。
(3)认证服务(UAA)获取接⼊⽅权限信息,并验证接⼊⽅是否合法。
(4)若登录⽤户以及接⼊⽅都合法,认证服务⽣成jwt令牌返回给接⼊⽅,其中jwt中包含了⽤户权限及接⼊⽅权限。
(5)后续,接⼊⽅携带jwt令牌对API⽹关内的微服务资源进⾏访问。
(6)API⽹关对令牌解析、并验证接⼊⽅的权限是否能够访问本次请求的微服务。
(7)如果接⼊⽅的权限没问题,API⽹关将原请求header中附加解析后的明⽂Token,并将请求转发⾄微服务。
(8)微服务收到请求,明⽂token中包含登录⽤户的⾝份和权限信息。因此后续微服务⾃⼰可以⼲两件事:
1. ⽤户授权拦截(看当前⽤户是否有权访问该资源)
2. 将⽤户信息存储进当前线程上下⽂(有利于后续业务逻辑随时获取当前⽤户信息)
流程所涉及到UAA服务、API⽹关这三个组件职责如下:
1)统⼀认证服务(UAA)
  它承载了OAuth2.0接⼊⽅认证、登⼊⽤户的认证、授权以及⽣成令牌的职责,完成实际的⽤户认证、授权功能。
2)API⽹关
  作为系统的唯⼀⼊⼝,API⽹关为接⼊⽅提供定制的API集合,它可能还具有其它职责,如⾝份验证、监控、负载均衡、缓存等。API⽹关⽅式的核⼼要点是,所有的接⼊⽅和消费端都通过统⼀的⽹关接⼊微服务,在⽹关层处理所有的⾮业务功能。
3. OAuth2.0
3.1 OAuth2.0介绍
  OAuth(开放授权)是⼀个开放标准,允许⽤户授权第三⽅应⽤访问他们存储在另外的服务提供者上的信息,⽽不需要将⽤户名和密码提供给第三⽅应⽤或分享他们数据的所有内容。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废⽌了OAuth1.0。很多⼤公司如Google,Yahoo,Microsoft等都提供了OAUTH认证服务,这些都⾜以说明OAUTH标准逐渐成为开放资源授权的标准。Oauth协议⽬前发展到2.0版本,1.0版本过于复杂,2.0版本已得到⼴泛应⽤。
3.2 OAuth2.0认证流程
1)客户端请求第三⽅授权
2)资源拥有者同意给客户端授权
3)客户端获取到授权码,请求认证服务器申请令牌
4)认证服务器向客户端响应令牌
5)客户端请求资源服务器的资源
6)资源服务器返回受保护资源
OAauth2.0包括以下⾓⾊:
1)客户端
  本⾝不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,⽐如:Android客户端、Web客户端(浏览器端)、客户端等。
2)资源拥有者
  通常为⽤户,也可以是应⽤程序,即该资源的拥有者。
3)授权服务器(也称认证服务器)
  ⽤于服务提供商对资源拥有的⾝份进⾏认证、对访问资源进⾏授权,认证成功后会给客户端发放令牌(access_token),作为客户端访问资源服务器的凭据。
4)资源服务器
  存储资源的服务器
现在还有⼀个问题,服务提供商能允许随便⼀个客户端就接⼊到它的授权服务器吗?答案是否定的,服务提供商会给准⼊的接⼊⽅⼀个⾝份,⽤于接⼊时的凭据:
client_id:客户端标识
client_secret:客户端秘钥
因此,准确来说,授权服务器对两种OAuth2.0中的两个⾓⾊进⾏认证授权,分别是资源拥有者、客户端。
4. Spring Cloud Security OAuth2
  Spring-Security-OAuth2是对OAuth2的⼀种实现,并且跟Spring Security相辅相成,与SpringCloud体系的集成也⾮常便利。
  OAuth2.0的服务提供⽅涵盖两个服务,即授权服务 (Authorization Server,也叫认证服务) 和资源服务 (ResourceServer),使⽤ Spring Security OAuth2 的时候你可以选择把它们在同⼀个应⽤程序中实现,也可以选择建⽴使⽤同⼀个授权服务的多个资源服务。
授权服务 (Authorization Server)应包含对接⼊端以及登⼊⽤户的合法性进⾏验证并颁发token等功能,对令牌的请求端点由 Spring MVC 控制器进⾏实现,下⾯是配置⼀个认证服务必须要实现的endpoints:
AuthorizationEndpoint 服务于认证请求。默认 URL: /oauth/authorize。
TokenEndpoint 服务于访问令牌的请求。默认 URL: /oauth/token。
资源服务 (Resource Server),应包含对资源的保护功能,对⾮法请求进⾏拦截,对请求中token进⾏解析鉴权等,下⾯的过滤器⽤于实现 OAuth 2.0 资源服务:OAuth2AuthenticationProcessingFilter⽤来对请求给出的⾝份令牌解析鉴权。
4.1 授权服务器配置
  可以⽤@EnableAuthorizationServer注解并继承AuthorizationServerConfifigurerAdapter来配置OAuth2.0 授权服务器。
在Confifig包下创建AuthorizationServer:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
//略...
}
AuthorizationServerConfifigurerAdapter要求配置以下⼏个类,这⼏个类是由Spring创建的独⽴的配置对象,它们会被Spring传⼊AuthorizationServerConfifigurer中进⾏配置。
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
  public AuthorizationServerConfigurerAdapter() {}
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {}
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {}
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {}
}
ClientDetailsServiceConfifigurer:⽤来配置客户端详情服务(ClientDetailsService),客户端详情信息在这⾥进⾏初始化,你能够把客户端详情信息写死在这⾥或者是通过数据库来存储调取详情信息。
AuthorizationServerEndpointsConfifigurer:⽤来配置令牌(token)的访问端点和令牌服务(token services)。
AuthorizationServerSecurityConfifigurer:⽤来配置令牌端点的安全约束
4.1.1 配置客户端详细信息
  ClientDetailsServiceConfifigurer 能够使⽤内存或者JDBC来实现客户端详情服务(ClientDetailsServi
ce),ClientDetailsService负责查ClientDetails,⽽ClientDetails 有⼏个重要的属性如下列表:
clientId:(必须的)⽤来标识客户的Id。
secret:(需要值得信任的客户端)客户端安全码,如果有的话。
scope:⽤来限制客户端的访问范围,如果为空(默认)的话,那么客户端拥有全部的访问范围。
authorizedGrantTypes:此客户端可以使⽤的授权类型,默认为空。
authorities:此客户端可以使⽤的权限(基于Spring Security authorities)。
/**
* ⽤来配置客户端详情服务(ClientDetailsService),客户端详情信息在这⾥进⾏初始化,
* 你能够把客户端详情信息写死在这⾥或者是通过数据库来存储调取详情信息。
*
* @param clients 客户端详情服务
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.withClientDetails(clientDetailsService);
/* clients.inMemory()// 使⽤in-memory存储,存储到内存中
.withClient("c1")// client_id
.secret(new BCryptPasswordEncoder().encode("secret"))//客户端密钥client_secret
.resourceIds("res1")//资源列表
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials                .scopes("all")// 允许
的授权范围
.autoApprove(false)//false跳转到授权页⾯
//加上验证回调地址
.redirectUris("")*/
;
}
4.1.2 管理令牌的三种⽅式
  AuthorizationServerTokenServices 接⼝定义了⼀些操作使得你可以对令牌进⾏⼀些必要的管理,令牌可以被⽤来加载⾝份信息,⾥⾯包含了这个令牌的相关权限。⾃⼰可以创建 AuthorizationServerTokenServices 这个接⼝的实现,则需要继承 DefaultTokenServices 这个类,⾥⾯包含了⼀些有⽤实现,你可以使⽤它来修改令牌的格式和令牌的存储。默认的,当它尝试创建⼀个令牌的时候,是使⽤随机值来进⾏填充的,除了持久化令牌是委托⼀个 TokenStore 接⼝来实现以外,这个类⼏乎帮你做了所有的事情。并且 TokenStore 这个接⼝有⼀个默认的实现,它就是 InMemo
ryTokenStore ,如其命名,所有的令牌是被保存在了内存中。除了使⽤这个类以外,你还可以使⽤⼀些其他的预定义实现,下⾯有⼏个版本,它们都实现了TokenStore接⼝:
1)InMemoryTokenStore:这个版本的实现是被默认采⽤的,它可以完美的⼯作在单服务器上(即访问并发量压⼒不⼤的情况下,并且它在失败的时候不会进⾏备份),⼤多数的项⽬都可以使⽤这个版本的实现来进⾏尝试,你可以在开发的时候使⽤它来进⾏管理,因为不会被保存到磁盘中,所以更易于调试。
2)JdbcTokenStore:这是⼀个基于JDBC的实现版本,令牌会被保存进关系型数据库。使⽤这个版本的实现时,你可以在不同的服务器之间共享令牌信息,使⽤这个版本的时候请注意把"spring-jdbc"这个依赖加⼊到你的classpath当中。
3)JwtTokenStore:这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进⾏编码(因此对于后端服务来说,它不需要进⾏存储,这将是⼀个重⼤优势),但是它有⼀个缺点,那就是撤销⼀个已经授权令牌将会⾮常困难,所以它通常⽤来处理⼀个⽣命周期较短的令牌以及撤销刷新令牌(refresh_token)。另外⼀个缺点就是这个令牌占⽤的空间会⽐较⼤,如果你加⼊了⽐较多⽤户凭证信息。JwtTokenStore 不会保存任何数据,但是它在转换令牌值以及授权信息⽅⾯与 DefaultTokenServices 所扮演的⾓⾊是⼀样的。
4.1.3 令牌访问端点配置
  AuthorizationServerEndpointsConfifigurer 这个对象的实例可以完成令牌服务以及令牌endpoint配置。
4.1.3.1 配置授权类型(Grant Types)
  AuthorizationServerEndpointsConfifigurer 通过设定以下属性决定⽀持的授权类型(Grant Types):
authenticationManager:认证管理器,当你选择了资源所有者密码(password)授权类型的时候,请设置这个属性注⼊⼀个 AuthenticationManager 对象。userDetailsService:如果你设置了这个属性的话,那说明你有⼀个⾃⼰的 UserDetailsService 接⼝的实现,或者你可以把这个东西设置到全局域上⾯去(例如GlobalAuthenticationManagerConfifigurer 这个配置对象),当你设置了这个之后,那么 "refresh_token" 即刷新令牌授权类型模式的流程中就会包含⼀个检查,⽤来确保这个账号是否仍然有效,假如说你禁⽤了这个账户的话。
4.1.3.2 配置授权端点的URL(Endpoint URLs):
AuthorizationServerEndpointsConfifigurer 这个配置对象有⼀个叫做 pathMapping() 的⽅法⽤来配置端点URL链接,它有两个参数:
第⼀个参数:String 类型的,这个端点URL的默认链接。
第⼆个参数:String 类型的,你要进⾏替代的URL链接。
以上的参数都将以 "/" 字符为开始的字符串,框架的默认URL链接如下列表,可以作为这个 pathMapping() ⽅法的第⼀个参数:
/oauth/authorize:授权端点。
/oauth/token:令牌端点。
/oauth/confifirm_access:⽤户确认授权提交端点。
/oauth/error:授权服务错误信息端点。
/oauth/check_token:⽤于资源服务访问的令牌解析端点。
/oauth/token_key:提供公有密匙的端点,如果你使⽤JWT令牌的话。
需要注意的是授权端点这个URL应该被Spring Security保护起来只供授权⽤户访问.
4.1.4 令牌端点的安全约束
  AuthorizationServerSecurityConfifigurer:⽤来配置令牌端点(Token Endpoint)的安全约束
4.1.5 web安全配置
  和secutity的WebSecurityConfigurerAdapter配置⼀样
项⽬下载地址:/donleo/springcloud-security-oauth2.git

本文发布于:2024-09-25 14:36:31,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/94470.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:认证   授权   服务   客户端
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议