java shiro security_安全框架Shiro和SpringSecurity的比较

两个基本的概念

安全实体:系统需要保护的具体对象数据

权限:系统相关的功能操作,例如基本的CRUD

Shiro

首先Shiro较之 Spring Security,Shiro在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势。

Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。如下是它所具有的特点:

易于理解的 Java Security API;

简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);

对角色的简单的签权(访问控制),支持细粒度的签权;

支持一级缓存,以提升应用程序的性能;

内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;

异构客户端会话访问;

非常简单的加密 API;

不跟任何的框架或者容器捆绑,可以独立运行。

Shiro四大核心功能:Authentication,Authorization,Cryptography,Session Management

525a7262b050ae0afc65825812fff832.png

Shiro架构

Shiro三个核心组件:Subject, SecurityManager 和 Realms.

Subject:主体,可以看到主体可以是任何可以与应用交互的 “用户”;

SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher;是 Shiro 的心脏;所有具体的交互都通过 SecurityManager 进行控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

两个配置类ShiroConfig和UserRealm

1 packagecom.example.shirodemo.config;2

3 importat.pollux.thymeleaf.shiro.dialect.ShiroDialect;4 importorg.apache.shiro.spring.web.ShiroFilterFactoryBean;5 importorg.apache.shiro.web.mgt.DefaultWebSecurityManager;6 importorg.springframework.beans.factory.annotation.Qualifier;7 importorg.springframework.context.annotation.Bean;8 importorg.springframework.context.annotation.Configuration;9

10 importjava.util.LinkedHashMap;11 importjava.util.Map;12

13 /**

14 * shiro配置类15 */

16 @Configuration17 public classShiroConfig {18 /**

19 * 创建ShiroFilterFactoryBean20 */

21 @Bean22 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){23 ShiroFilterFactoryBean shiroFilterFactoryBean=newShiroFilterFactoryBean();24 //设置安全管理器

25 shiroFilterFactoryBean.setSecurityManager(securityManager);26 //添加Shiro拦截器

27 /**

28 * Shiro 内置过滤器,可以实现权限相关的拦截器29 * anon:无需认证(登录)可以直接访问30 * authc:必须认证才能访问31 * user:如果使用rememberMe的功能才可以访问32 * perms:该资源得到资源权限才可以访问33 * role:该资源必须得到角色权限才可以访问34 */

35 Map filterMap=new LinkedHashMap<>();36 /*filterMap.put("/add","authc");37 filterMap.put("/update","authc");*/

38 //filterMap.put("/test","anon");

39 filterMap.put("/login","anon");40 //添加Shiro授权拦截器

41 filterMap.put("/add","perms[添加]");42 filterMap.put("/foresee","perms[预言未来]");43 filterMap.put("/update","perms[修改]");44 filterMap.put("/delete","perms[删除]");45 //filterMap.put("/update","perms[]");46 //filterMap.put("/delete","perms[]");47 //filterMap.put("/getAll","perms[]");

48 filterMap.put("/*","authc");49 //跳转到登陆的页面

50 shiroFilterFactoryBean.setLoginUrl("/tologin");51 //设置未授权的页面

52 shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");53 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);54

55 returnshiroFilterFactoryBean;56 }57 /**

58 * 创建DefaultWebSecurityManager59 */

60 @Bean("securityManager")61 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){62 DefaultWebSecurityManager securityManager=newDefaultWebSecurityManager();63 //关联Realm

64 securityManager.setRealm(userRealm);65 returnsecurityManager;66 }67 /**

68 * 创建Realm69 */

70 @Bean("userRealm")71 publicUserRealm getRealm(){72 UserRealm userRealm=newUserRealm();73 returnuserRealm;74 }75 /**

76 * 配置shiroDialect,用于thymeleaf和shiro标签配合使用77 */

78 @Bean79 publicShiroDialect getShiroDialect(){80 ShiroDialect shiroDialect=newShiroDialect();81 returnshiroDialect;82 }83 }

packagecom.example.shirodemo.config;importcom.example.shirodemo.bean.Permission;importcom.example.shirodemo.bean.User;importcom.example.shirodemo.service.IPermissionService;importcom.example.shirodemo.service.IUserService;importorg.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.authz.SimpleAuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.subject.PrincipalCollection;importorg.apache.shiro.subject.Subject;importorg.springframework.security.core.GrantedAuthority;importorg.springframework.security.core.authority.SimpleGrantedAuthority;importjavax.annotation.Resource;importjava.util.ArrayList;importjava.util.List;/*** 自定义Realm*/

public class UserRealm extendsAuthorizingRealm {

@ResourceprivateIUserService userService;

@ResourceprivateIPermissionService permissionService;/*** 执行授权逻辑

*@paramprincipalCollection

*@return

*/@OverrideprotectedAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

System.out.println("执行授权逻辑");/*** 给资源授权*/SimpleAuthorizationInfo simpleAuthorizationInfo=newSimpleAuthorizationInfo();//添加授权字符串//simpleAuthorizationInfo.addStringPermission("user:add");//--------------------认证账号

Subject subject=SecurityUtils.getSubject();

User user=(User)subject.getPrincipal();

User user1=userService.findById(user.getId());if(user1==null){//用户名不存在

return null;

}//-------------------开始授权

List permissions =permissionService.getPermissionByUserId(user1.getId());for(Permission per : permissions) {

simpleAuthorizationInfo.addStringPermission(per.getName());

System.out.println("拥有权限:"+per.getName());

}returnsimpleAuthorizationInfo;

}/*** 执行认证逻辑

*@paramauthenticationToken

*@return*@throwsAuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throwsAuthenticationException {

System.out.println("执行认证逻辑");/*** 判断ShiroRealm逻辑UsernamePasswordToken是否正确*/

//1判断用户名

UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)authenticationToken;

User user=userService.findByname(usernamePasswordToken.getUsername());if(user==null){//用户名不存在

return null;

}//判断密码是否正确

return new SimpleAuthenticationInfo(user,user.getPassword(),"");

}

}

认证过程

1 /**

2 * 登录逻辑处理3 */

4 @RequestMapping("/login")5 publicString login(User user, Model model) {6 /**

7 *使用shiro编写认证操作8 */

9 //1:获取subject

10 Subject subject =SecurityUtils.getSubject();11 //2:封装用户账号和密码

12 UsernamePasswordToken usernamePasswordToken = newUsernamePasswordToken(user.getUsername(), user.getPassword());13 //3:执行登录方法

14 try{15 subject.login(usernamePasswordToken);16 model.addAttribute(user);17 //登录成功18 //成功后跳转到19 //return "redirect:/test";

20 return "/test";21 } catch(UnknownAccountException e) {22 //e.printStackTrace();23 //登录失败用户名不存在

24 model.addAttribute("msg","用户名不存在");25 return "login";26 }catch(IncorrectCredentialsException e){27 //登录失败密码错误

28 model.addAttribute("msg","密码错误");29 return "login";30 }31 }32 }

Subject拿到用户数据后走UserRealm 类里面的认证逻辑,授权过程比较简单可以看你上面的代码,

Shiro配置拦截器

//添加Shiro拦截器

27         /**

28 * Shiro 内置过滤器,可以实现权限相关的拦截器

29 *     anon:无需认证(登录)可以直接访问

30 *     authc:必须认证才能访问

31 *     user:如果使用rememberMe的功能才可以访问

32 *     perms:该资源得到资源权限才可以访问

33 *     role:该资源必须得到角色权限才可以访问

34          */

Spring Security

除了不能脱离Spring,shiro的功能它都有。而且Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。Spring Security的权限细粒度更高,毕竟Spring Security是Spring家族的。

Spring Security一般流程为:

①当用户登录时,前端将用户输入的用户名、密码信息传输到后台,后台用一个类对象将其封装起来,通常使用的是UsernamePasswordAuthenticationToken这个类。

②程序负责验证这个类对象。验证方法是调用Service根据username从数据库中取用户信息到实体类的实例中,比较两者的密码,如果密码正确就成功登陆,同时把包含着用户的用户名、密码、所具有的权限等信息的类对象放到SecurityContextHolder(安全上下文容器,类似Session)中去。

③用户访问一个资源的时候,首先判断是否是受限资源。如果是的话还要判断当前是否未登录,没有的话就跳到登录页面。

④如果用户已经登录,访问一个受限资源的时候,程序要根据url去数据库中取出该资源所对应的所有可以访问的角色,然后拿着当前用户的所有角色一一对比,判断用户是否可以访问。

注:

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

OpenID 系统的第一部分是身份验证,即如何通过 URI 来认证用户身份。目前的网站都是依靠用户名和密码来登录认证,这就意味着大家在每个网站都需要注册用户名和密码,即便你使用的是同样的密码。如果使用 OpenID ,你的网站地址(URI)就是你的用户名,而你的密码安全的存储在一个 OpenID 服务网站上(你可以自己建立一个 OpenID 服务网站,也可以选择一个可信任的 OpenID 服务网站来完成注册)。

与OpenID同属性的身份识别服务商还有ⅥeID,ClaimID,CardSpace,Rapleaf,Trufina ID Card等,其中ⅥeID通用账户的应用最为广泛。

Spring Security和Shiro

相同点:

1:认证功能

2:授权功能

3:加密功能

4:会话管理

5:缓存支持

6:rememberMe功能.......

不同点:

优点:

1:Spring Security基于Spring开发,项目中如果使用Spring作为基础,配合Spring Security做权限更加方便,而Shiro需要和Spring进行整合开发

2:Spring Security功能比Shiro更加丰富些,例如安全防护

3:Spring Security社区资源比Shiro丰富

缺点:

1:Shiro的配置和使用比较简单,Spring Security上手复杂

2:Shiro依赖性低,不需要任何框架和容器,可以独立运行,而Spring Security依赖于Spring容器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 2043. 简易银行系统

文章目录1. 题目2. 解题1. 题目 你的任务是为一个很受欢迎的银行设计一款程序&#xff0c;以自动化执行所有传入的交易&#xff08;转账&#xff0c;存款和取款&#xff09;。 银行共有 n 个账户&#xff0c;编号从 1 到 n 。每个账号的初始余额存储在一个下标从 0 开始的整数…

LeetCode 2044. 统计按位或能得到最大值的子集数目(状态压缩DP)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 nums &#xff0c;请你找出 nums 子集 按位或 可能得到的 最大值 &#xff0c;并返回按位或能得到最大值的 不同非空子集的数目 。 如果数组 a 可以由数组 b 删除一些元素&#xff08;或不删除&#xff09;得到&#xff0c;则…

fastapi 请求体 - 多个参数 / 字段Field / 嵌套模型

文章目录1. 混合使用 Path、Query 和请求体参数2. 多个请求体参数3. 请求体中的单一值4. 多个请求体参数和查询参数5. 嵌入单个请求体参数6. 字段7. 嵌套模型7.1 List 字段7.2 子模型作为类型8. 特殊类型校验9. 带有一组子模型的属性10. 任意 dict 构成的请求体learn from http…

java ltpa_LTPA Cookie原理

1. 什么是LTPA?Lightweight Third-Party Authentication (LTPA)是IBM Websphere和Domino产品中使用单点登录技术。当服务器配置好LTPA认证方式&#xff0c;用户通过浏览器成功登录后&#xff0c;服务器会自动发送一个session cookie给浏览器&#xff1b;此cookie中包含一个LTP…

fastapi 模式的额外信息,示例 / Cookie参数 / Header参数

文章目录1. Pydantic schema_extra2. Field 的附加参数3. Body 额外参数4. Cookie 参数5. Header 参数5.1 重复的 headerslearn from https://fastapi.tiangolo.com/zh/tutorial/schema-extra-example/ 添加一个将在文档中显示的 example 1. Pydantic schema_extra from typ…

Android(java)学习笔记171:服务(service)之绑定服务调用服务里面的方法

1.绑定服务调用服务里面的方法&#xff0c;图解&#xff1a; 步骤&#xff1a; &#xff08;1&#xff09;在Activity代码里面绑定 bindService&#xff08;&#xff09;&#xff0c;以bind的方式开启服务 &#xff1b; bindService&#xff08;intent, new MyConn(), BIND_AUT…

LeetCode 1909. 删除一个元素使数组严格递增

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;如果 恰好 删除 一个 元素后&#xff0c;数组 严格递增 &#xff0c;那么请你返回 true &#xff0c;否则返回 false 。 如果数组本身已经是严格递增的&#xff0c;请你也返回 true 。 数组…

ATS push cache 测试

测试 ATS 注入缓存 参考了&#xff1a; http://serverfault.com/questions/471684/push-content-to-apache-traffic-servers-cache 得到返回&#xff1a;HTTP/1.0 400 Response Not Cachable 搜索得知&#xff0c;头部传入信息太少&#xff0c;必须包含反映时间的项。那个回答应…

fastapi 响应模型 / 响应状态码 / 表单参数

文章目录1. response_model2. 添加输出模型3. 响应模型编码参数4. response_model_include 和 response_model_exclude5. 代码复用&#xff1a;继承6. Union7. 任意 dict 的响应8. 响应状态码9. 表单参数learn from https://fastapi.tiangolo.com/zh/tutorial/response-model/ …

java对象内存模型_Java对象的内存模型

众所周知&#xff0c;函数调用在内存中是通过压栈&#xff0c;退栈实现的&#xff0c;而Java的方法调用则是在JVM栈中通过栈帧实现的&#xff0c;且所有的Java对象都只在堆上分配内存&#xff0e;那么一个Java对象在堆内存里到底长啥样呢&#xff1f;实际上&#xff0c;当一个对…

fastapi 请求文件 / 表单 / 处理错误 / 路径操作配置 / jsonable_encoder

文章目录1. File 参数2. 多文件上传3. 请求表单与文件4. 处理错误5. 自定义响应头6. 自定义异常处理器7. 覆盖默认异常处理器8. 使用 RequestValidationError 的请求体9. 复用 FastAPI 异常处理器10. 路径操作参数配置10.1 status_code&#xff0c;tags10.2 summary&#xff0c…

fastapi PUT更新数据 / PATCH部分更新

文章目录1. PUT 更新2. 用 PATCH 进行部分更新learn from https://fastapi.tiangolo.com/zh/tutorial/body-updates/1. PUT 更新 注意&#xff0c;put 没有指定的值&#xff0c;会被重置为默认值 from typing import List, Optionalfrom fastapi import FastAPI from fastap…

Chrome 扩展 最近的历史 HistoryBar v1.1

说明 以前用过一段时间傲游浏览器&#xff0c;渐渐的习惯了它的鼠标手势和一些细微的人性化的功能。比方地址栏左边的“近期訪问的页面”button。能够方便的找到近期 20 条历史记录。 但后来因为某些原因又回到了 Chrome 的怀抱&#xff0c;于是就没有了这些不起眼但非常好用的…

LeetCode 2047. 句子中的有效单词数

文章目录1. 题目2. 解题1. 题目 句子仅由小写字母&#xff08;a 到 z&#xff09;、数字&#xff08;0 到 9&#xff09;、连字符&#xff08;-&#xff09;、标点符号&#xff08;!、. 和 ,&#xff09;以及空格&#xff08; &#xff09;组成。 每个句子可以根据空格分解成 …

LeetCode 2048. 下一个更大的数值平衡数(枚举)

文章目录1. 题目2. 解题1. 题目 如果整数 x 满足&#xff1a;对于每个数位 d &#xff0c;这个数位 恰好 在 x 中出现 d 次。 那么整数 x 就是一个 数值平衡数 。 给你一个整数 n &#xff0c;请你返回 严格大于 n 的 最小数值平衡数 。 示例 1&#xff1a; 输入&#xff1a…

LeetCode 2049. 统计最高分的节点数目(DFS)

文章目录1. 题目2. 解题1. 题目 给你一棵根节点为 0 的 二叉树 &#xff0c;它总共有 n 个节点&#xff0c;节点编号为 0 到 n - 1 。 同时给你一个下标从 0 开始的整数数组 parents 表示这棵树&#xff0c;其中 parents[i] 是节点 i 的父节点。 由于节点 0 是根&#xff0c;所…

python源文件编码的含义_【原创】Python 源文件编码解读

以下内容源于对 PEP-0263 的翻译和解读&#xff0c;同时给出了一些网上网友的说法。 我是分割线 PEP 0263 -- Defining Python Source Code Encodings【摘要】给出声明 Python 源文件编码的语法。该编码信息后续会被 Python 解析器用于解析源文件。这种方式增强了对源文件中 U…

MyEclipse中SVN的常见的使用方法

本次主要内容&#xff1a; 一 、导入项目 &#xff08;Checkout&#xff09;。从svn资源库检出 二 、更新 &#xff08;Update&#xff09; 三、锁&#xff08;对要修改的文件加锁&#xff0c;防止文件冲突&#xff09; 四、提交&#xff08;项目修改后的提交&#xff09; 五、…

fastapi 路径依赖项Depends / 装饰器依赖dependencies / 全局依赖 / 带 yield 的依赖

文章目录1. 依赖项2. 类作为依赖3. 子依赖项3.1 多次使用同一个依赖项4. 路径操作装饰器依赖项5. 全局依赖项6. 带 yield 的依赖项7. 使用带 yield 上下文管理器作为依赖项learn from https://fastapi.tiangolo.com/zh/tutorial/dependencies/ 1. 依赖项 只能传给 Depends 一…

fastapi 安全性 / APIRouter / BackgroundTasks / 元数据 / 测试调试

文章目录1. 例子2. 获取当前用户3. 使用密码和 Bearer 的简单 OAuth24. 使用&#xff08;哈希&#xff09;密码和 JWT Bearer 令牌的 OAuth25. 多个应用文件5.1 APIRouter6. BackgroundTasks7. 元数据7.1 标题、描述和版本7.2 openapi_tags 标签元数据7.3 OpenAPI URL7.4 文档 …