Spring Security、Shiro、JWT权限认证

JWT和Spring Security、Shiro的区别

jwt只是一个生成token的机制,而Spring Security、Shiro这两个框架是用来后台做权限认证,管理,筛选的框架

JWT

jwt是什么?

JWT又名Json Web Token,基于数字签名,定义了一个紧凑、字包含的方式,用于json在各方之间安全传输信息。

使用场景

一般用于授权认证和数据交换:

  • Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用
  • Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
JWT架构图

在这里插入图片描述

JWT由什么组成的

JWT由Header、Payload、Signature组成,它们之间用 . 连接。例如
111(Header).222(Payload).333(Signature)

  • Header

由token的类型和算法名称组成json,然后在对这个json进行BASE64编码

json格式如下;
{
"alg":"RSA",
"type":"JWT"
}
  • Payload

JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。
Registered claims : 这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
Public claims: 可以随意定义。
Private claims: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。

{
"admin":"true",
"name":"zzz"
}

payload是对上面json进行base64编码,然后放入jwt的第二部分

  • Signature

为了得到签名,必须要具备前两个条件(base64 编码过后的header、payload),还需要一个密钥,签名算法使用的header中的指定的算法,然后对他们签名

RSA(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

官网解释图:
在这里插入图片描述

JWT是如何工作的

用户从客户端登录成功后,后端会返回一个jwt token,然后这个token就是用户凭证了,通常token有失效时间(通常都放在redis里面保存)
带着token访问受保护的api接口的时候,一般都会把token放在Authorization headerBearer schema的值里。好处是这样不会使用cookie。
在这里插入图片描述

流程如下:
  • 客户端访问授权服务器,请求授权;
  • 返回一个token
  • 然后用token访问受保护的资源
postman截图

在这里插入图片描述

和老版本的session相比的优点

因为http是无状态的,无法记录请求方,于是大家都会发送cookie到服务器端,或者是在服务器端上记录sessionId
问题点:

  • 服务器端记录大量的sessionid,对内存开销有影响
  • 跨域问题
  • 安全性

JWT的好处:

  • token存放在客户端,减轻服务器端的负担,可以让负载均衡器将用户传递到任意服务器
  • 每次请求都需要带上token,没有会话,安全性大
JWT的流程使用
  1. 用户携带用户名和密码请求访问
  2. 服务器校验用户凭据
  3. 应用提供一个token给客户端
  4. 客户端存储token,并且在随后的每一次请求中都带着它
  5. 服务器校验token并返回数据

Spring Security

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC(控制反转),DI( 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。它是一个轻量级的安全框架,它确保基于Spring的应用程序提供身份验证和授权支持。它与Spring MVC有很好地集成,并配备了流行的安全算法实现捆绑在一起。安全主要包括两个操作“认证”与“验证”(有时候也会叫做权限控制)。“认证”是为用户建立一个其声明的角色的过程,这个角色可以一个用户、一个设备或者一个系统。“验证”指的是一个用户在你的应用中能够执行某个操作。在到达授权判断之前,角色已经在身份认证过程中建立了。

它的设计是基于框架内大范围的依赖的,可以被划分为以下几块。

  1. Web/Http 安全:这是最复杂的部分。通过建立 filter 和相关的 service bean 来实现框架的认证机制。当访问受保护的 URL 时会将用户引入登录界面或者是错误提示界面。
  2. 业务对象或者方法的安全:控制方法访问权限的。
  3. AuthenticationManager:处理来自于框架其他部分的认证请求。
  4. AccessDecisionManager:为 Web 或方法的安全提供访问决策。会注册一个默认的,但是我们也可以通过普通 bean 注册的方式使用自定义的 AccessDecisionManager。
  5. AuthenticationProvider:AuthenticationManager 是通过它来认证用户的。
  6. UserDetailsService:跟 AuthenticationProvider 关系密切,用来获取用户信息的

工作流程
在WEB项目中,它基于fiter。Spring Security 在 Filter 中创建 Authentication 对象,并调用 AuthenticationManager 进行校验

Spring Security维护了一个fiter chain,按照特定的顺序执行(filter之间有以来)
1.ChannelProcessingFilter

核心组件

  • SecurityContext
  • SecurityContextHolder
  • Authentication
  • Userdetails
  • AuthenticationManager,

SecurityContext:安全上下文,用户通过Spring Security 的校验之后,验证信息存储在SecurityContext中,SecurityContext的接口定义

//存取安全上下文
public interface SecurityContext extends Serializable {
 /**
 * Obtains the currently authenticated principal, or an authentication request token.
 *
 * @return the <code>Authentication</code> or <code>null</code> if no authentication
 * information is available
 */
 Authentication getAuthentication();
 /**
 * Changes the currently authenticated principal, or removes the authentication
 * information.
 *
 * @param authentication the new <code>Authentication</code> token, or
 * <code>null</code> if no further authentication information should be stored
 */
 void setAuthentication(Authentication authentication);
}

SecurityContextHolder
维持SecurityContext的实例,该上下文将上下文存储为HTTP请求之间的HttpSession属性。它会为每个请求恢复上下文SecurityContextHolder,并且最重要的是,在请求完成时清除SecurityContextHolder。SecurityContextHolder是一个类,他的功能方法都是静态的。它可以自定义SecurityContext的jvm存储策略,里面实现方法多用于存储当前认证信息

/**
* jvm策略
* MODE_THREADLOCAL(默认jvm设置。存在线程中)
* MODE_INHERITABLETHREADLOCAL(也是存在线程中,但是子线程可以获得浮现出)
* MODE_GLOBAL:SecurityContext 在所有线程中都相同
**/
//和session存储sessinid一样
SecurityContextHolder.getContext().setAuthentication(token);

Authentication
Authentication是一个接口,一般在Spring Security中表示登录用户是谁。

public interface Authentication extends Principal, Serializable {
 //获取用户的角色信息
 Collection<? extends GrantedAuthority> getAuthorities();
 //获取证明用户认证的信息,通常情况下获取到的是密码等信息
 Object getCredentials();
 //获取用户的额外信息,(这部分信息可以是我们的用户表中的信息)
 Object getDetails()
 //获取用户身份信息,在未认证的情况下获取到的是用户名,在已认证的情况下获取到的是 UserDetails ;
 Object getPrincipal();(UserDetails也是一个接口,里边的方法有getUsername,getPassword等)//获取当前 Authentication 是否已认证。
 boolean isAuthenticated();
 //设置当前 Authentication 是否已认证(true or false)
 void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

AuthenticationManager:
是一个校验Authentication的接口,如果失败会抛出一个抽象类AuthenticationException的异常,因为不能实例化抽象类,所以无法抛出AuthenticationException异常,所以一般都是实现类DisabledException,LockedException,BadCredentialsException(密码错误的异常)

public interface AuthenticationManager {
 Authentication authenticate(Authentication authentication)
 throws AuthenticationException;
}

UserDetails
存储用户信息;

public interface UserDetails extends Serializable {
 Collection<? extends GrantedAuthority> getAuthorities();//获取用户的角色信息
 String getPassword();
 String getUsername();
 boolean isAccountNonExpired();//是否过期
 boolean isAccountNonLocked();//是否被锁定
 boolean isCredentialsNonExpired();//密码是否失效
 boolean isEnabled();//账号是否可用
}

UserDetailsService
UserDetailsService是一个获取UserDetails的接口,只有一个loadUserByUsername(final String login)方法。
实际开发中

自定义一个实现类去实现UserDetailsService接口,并且实现loadUserByUsername这个方法,可以通过查询数据库/缓存来获取用户信息,然后组成一个UserDetails并返回,如果没有查询数据,那就抛出异常(org.springframework.security.core.userdetails.UsernameNotFoundException)去告诉spring security去处理。

工作原理及应用范围

Spring security 是基于filter的,filter按照顺序去执行,根据filterChain去调用下一个filter,Spring Security 在 Filter 中创建 Authentication 对象,并调用 AuthenticationManager 进行校验。Spring Security有一个filterChain去管理filter,根据需要的功能在配置中配置。
流程

  1. spring security 的核心是基于filter
  2. 入口filter是springSecurityFilterChain(它会被DelegatingFilterProxy委托来执行过滤任务)
  3. springSecurityFilterChain实际上是FilterChainProxy (一个filter)
  4. FilterChainProxy里边有一个SecurityFilterChain集合,doFIlter的时候会从其中取

Shiro

Apache Shiro是Java的一个安全框架,在轻量级的程序应用更广泛,简化了Spring security的功能,提供了处理身份认证,授权,企业会话管理和加密的功能。

应用领域
  1. 验证用户
  2. 对用户执行访问控制,如:
    判断用户是否拥有角色admin。
    判断用户是否拥有访问的权限
  3. 在任何环境下使用 Session API。例如CS程序。
  4. 可以使用多个用户数据源。例如一个是oracle用户库,另外一个是mysql用户库。
  5. 单点登录(SSO)功能。
  6. “Remember Me”服务 ,类似购物车的功能,shiro官方建议开启
核心领域:
  1. 身份验证Authentication(重要模块)
  2. 授权Authorization(重要模块)
  3. 会话管理Session Management(重要模块)
  4. 加密Cryptography(重要模块)
  5. web support:Web支持,可以非常容易的集成到Web环境(次要)
  6. Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;(次要)
  7. Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;(次要)
  8. Testing:提供测试支持;(次要)
  9. Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;(次要)
  10. Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了(次要)

在这里插入图片描述

核心组件:
  1. Subject 主体
  2. SecurityManager 安全管理器 (Subject 的管理者)
  3. Realms 域

在这里插入图片描述
Subject
代表了与当前应用交互的任何东西,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者
SecurityManager
SecurityManager 是 Shiro的核心,初始化时协调各个模块运行。然而,一 旦 SecurityManager协调完毕,SecurityManager 会被单独留下,且我 们只需要去操作Subject即可,无需操SecurityManager 。 但是我们 得知道,当我们正与一个 Subject 进行交互时,实质上是 SecurityManager在处理 Subject 安全操作
Shiro
Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

常用shiro 注解
@RequiresAuthentication
验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。
@ RequiresUser
验证用户是否被记忆,user有两种含义: 一种是成功登录的(subject.isAuthenticated() 结果为true); 另外一种是被记忆的( subject.isRemembered()结果为true)。
@ RequiresGuest
验证是否是一个guest的请求,与@ RequiresUser完全相反。 换言之,RequiresUser == ! RequiresGuest 。 此时subject.getPrincipal() 结果为null.
@ RequiresRoles
例如:@RequiresRoles(“aRoleName”);void someMethod(); 如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个 权限则会抛出异常AuthorizationException。
@RequiresPermissions
例如: @RequiresPermissions( {“file:read”, “write:aFile.txt”} ) void someMethod();要求subject中必须同时含有file:read和write:aFile.txt的权限才能执行方法someMethod()。否则抛出异常AuthorizationException。

shiro和spring security差别

Spring security 与apache shiro 差别:
a)shiro配置更加容易理解,容易上手;security配置相对比较难懂。
b)在spring的环境下,security整合性更好。Shiro对很多其他的框架兼容性更好,号称是无缝集成。
c)shiro 不仅仅可以使用在web中,它可以工作在任何应用环境中。 d)在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。 e)Shiro提供的密码加密使用起来非常方便。
d)控制精度: 注解方式控制权限只能是在方法上控制,无法控制类级别访问。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值