- 浏览: 22040 次
- 性别:
- 来自: 深圳
-
最新评论
Shiro简介及与spring集成
【IT168 技术】Apache Shiro是一个强大的,易用的Java安全框架。它被用作于认证,授权,加密,session管理。依赖于Shiro简单易懂的API,就可以快速的构建包括手机,大型web和商业应用。
1、权限基础
两个基本的概念
——安全实体:就是被权限系统保护的对象,比如工资数据。
——权限:就是需要被校验的行为,比如查看、修改等。
分配权限:
——把对某些安全实体的某些权限分配给某些人员。
——是向数据库里面添加数据、或是维护数据的过程
权限验证(权限匹配):
——判断某个人员或程序对某个安全实体是否拥有某个或某些权限。
——从数据库中获取相应数据进行匹配的过程。
权限的继承性:
如果多个安全实体存在包含关系,而某个安全实体没有权限限制,则它会继承包含它的安全实体的相应权限。
权限的最近匹配原则:
如果多个安全实体存在包含关系,而某个安全实体没有权限限制,那么它会向上寻找并匹配相应权限限制,直到找到一个离这个安全实体最近的拥有相应权限限制的安全实体为止。如果把整个层次结构都寻找完了都没有匹配到相应权限限制的话,那就说明所有人对这个安全实体都拥有这个相应的权限限制。
2、Shiro架构与功能介绍
Authentication: 认证。即验证是哪个用户登录。
Authorization:也被称为访问控制,即决定当前登录用户是否有权限去访问受保护的资源。
Cryptography:通过加密算法保护数据安全。
Session Management: 当用户使用你的应用是自身携带的数据。
Web Integration: 虽然Shiro是设计用来确保任何基于JVM的应用,但是很多时候是用来保护Web应用。
Integrations:可以很好的集成其他的技术和框架。
下图展示了Shiro的的四大核心功能和所支持的其它特性。
三大核心组件
Subject:正与系统进行交互的人,或某一个第三方服务。所有Subject实例都被绑定到(且这是必须的)一个SecurityManager上。
SecurityManager:Shiro架构的心脏,用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当Shiro与一个Subject进行交互时,实质上是幕后的SecurityManager处理所有繁重的Subject安全操作。
Realms:本质上是一个特定安全的DAO。当配置Shiro时,必须指定至少一个Realm用来进行身份验证和/或授权。Shiro提供了多种可用的Realms来获取安全相关的数据。如关系数据库(JDBC),INI及属性文件等。可以定义自己Realm实现来代表自定义的数据源。
Shiro架构图
Authenticator:执行对用户的身份验证(登录)的组件。Authenticator从一个或多个Realm中获得数据以验证用户的身份。
若存在多个realm,则接口AuthenticationStrategy会确定什么样算是验证成功(例如,如果一个Realm成功,而其他的均失败,是否登录成功)。
Authorizer:验证用户能否访问应用中的受保护的资源
SessionManager:可在任何应用或架构层一致地使用 Session API
SessionDAO:SessionManager执行Session持久化(CRUD)操作。
CacheManager :对Shiro组件提供缓存支持。
Cryptography:Shiro的API大幅度简化Java API中繁琐的密码加密
Realms:Shiro通过Realms来获取相应的安全数据
Realm 实现关系:
认证
Step 1:应用程序代码调用Subject.login方法,传递创建好的包含终端用户的Principals(身份)和Credentials(凭证)的AuthenticationToken实例
Step 2:Subject实例,通常为DelegatingSubject(或子类)委托应用程序的SecurityManager通过调用securityManager.login(token)开始真正的验证。
Step3:SubjectManager接收token,调用内部的Authenticator实例调用 authenticator.authenticate(token)。 Authenticator通常是一个ModularRealmAuthenticator实例,支持在身份验证中协调一个或多个Realm实例。
Step 4:如果应用程序中配置了一个以上的Realm,ModularRealmAuthenticator实例将利用配置好的AuthenticationStrategy来启动Multi-Realm认证尝试。在Realms被身份验证调用之前,期间和以后,AuthenticationStrategy被调用使其能够对每个Realm的结果作出反应。
Step 5:每个配置的 Realm 用来帮助看它是否支持提交的AuthenticationToken。如果支持,那么支持Realm的getAuthenticationInfo方法将会伴随着提交的token被调用。getAuthenticationInfo方法有效地代表一个特定Realm的单一的身份验证尝试。
授权
Step 1:应用程序或框架代码调用任何Subject 的hasRole*, checkRole*, isPermitted*,或者checkPermission*方法的变体,传递任何所需的权限
Step 2:Subject的实例—通常是DelegatingSubject(或子类),调用securityManager的对应的方法。
Step 3:SecurityManager调用org.apache.shiro.authz.Authorizer接口的对应方法。默认情况下,authorizer 实例是一个ModularRealmAuthorizer实例,它支持协调任何授权操作过程中的一个或多个Realm实例。
Step 4:每个配置好的Realm被检查是否实现了相同的Authorizer接口。如果是,Realm各自的hasRole*, checkRole*,isPermitted*,或checkPermission*方法将被调用。
注销
logout(注销):currentUser.logout;
调用logout方法时,现有Session将失效,而且身份将失去关联(在Web应用程序中,RememberMe cookie将被删除)。
在Subject注销后,该Subject的实例被再次认为是匿名的。
注意:WEB应用程序记住身份往往依靠Cookie,然而Cookie只能在Response被返回后被删除,所以建议在调用subject.logout后立即向终端重定向一个新的视图或页面。这样即能保证与安全相关的Cookie都能像预期的一样被删除。
Shiro中默认的过滤器
基于注解
Shiro提供的注解
@RequiresAuthentication :要求当前Subject已经在当前的session中被验证通过才能被注解的类/实例/方法访问或调用。
@RequiresGuest :要求当前的Subject是一个“guest”,也就是他们必须是在之前的session中没有被验证或记住才能被注解的类/实例/方法访问或调用。
@RequiresPermissions:要求当前的Subject被允许一个或多个权限,以便执行注解的方法,比如:@RequiresPermissions("account:create")
@RequiresRoles:要求当前的Subject拥有所有指定的角色。如果他们没有,则该方法将不会被执行,而且AuthorizationException异常将会被抛出。比如:@RequiresRoles("administrator")
@RequiresUser:需要当前的Subject是一个应用程序用户才能被注解的类/实例/方法访问或调用。要么是通过验证被确认,或者在之前session中的‘RememberMe’服务被记住。
基于标签
需要在jsp页面中倒入shiro 标签
guest 标签
guest标签将显示它包含的内容,仅当当前的Subject 被认为是guest时。
guest是指没有身份ID的任何Subject:没有登录也没有在上一次的访问中被记住(RememberMe 服务)
guest标签与user标签逻辑相反。
Hi there! Please Loginor
Signuptoday!
user标签
user标签将显示它包含的内容,仅当当前的Subject 被认为是user时。
user在上下文中被定义为一个已知身份ID的Subject,或是成功通过身份验证及通过RememberMe服务的。
该标签在语义上与authenticated 标签是不同的,authenticated标签更为严格。
User标签与guest标签逻辑相反。
authenticated 标签
当当前用户在当前会话中成功地通过了身份验证authenticated标签才会显示包含的内容。比user标签更为严格。在逻辑上与notAuthenticated标签相反。
Update your contact information.
notAuthenticated标签
当前Subject还没有在其当前会话中成功地通过验证,将会显示它所包含的内容
Please loginin order to update your credit card information.
principal标签
标签将会输出Subject的主体(标识属性)或主要的属性
Hello, , how are you today?
Typed principal
User ID:
Principal property
Hello,
hasRole标签
当前Subject被分配了具体的角色时显示它所包含的内容。hasRole标签与lacksRole标签逻辑相反。
Administer the system
lacksRole标签
Sorry, you are not allowed to administer the system.
hasAnyRole标签
当前的Subject被分配了任意一个来自于逗号分隔的角色名列表中的具体角色,将会显示它所包含的内容。
You are either a developer, project manager, or administrator.
hasPermission标签
当前Subject拥有特定的权限时,会显示它所包含的内容。hasPermission标签与lacksPermission标签逻辑相反。
Create a new User
lacksPermission标签
当前Subject没有拥有(蕴含)特定的权限,将会显示它所包含的内容。也就是说,用户没有特定的能力。
Sorry, you are not allowed to delete user accounts.
3、Spring集成Shiro
配置自定义Realm:实现自定义认证和授权
配置Shiro实体类使用的缓存策略
配置SecurityManager
配置保证Shiro内部Bean声明周期都得到执行的Lifecycle Bean后置处理器
配置AOP式方法级权限检查
配置Shiro Filter
基于Maven构建项目
web.xml
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="true">
applicationContext.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
applicationContext-shiro.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
/** = anon
springDispatherServlet-servlet.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
代码实现
自定义Realm
@Component("myRealm")
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权方法,在配有缓存的情况下,只加载一次。
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal;
List
Set
for (Authority authority : authorities){
roles.add(authority.getName);
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo;
info.setRoles(roles);
return info;
* 登录认证
* @param token
* @return
* @throws AuthenticationException
*/
@Transactional
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken uptoken = (UsernamePasswordToken) token;
String username = uptoken.getUsername;
User user = userService.findUserByLoginName(username);
if( user == null ) {
throw new UnknownAccountException("用户名"+username+"不存在.");
}
if (user.getEnabled != 1){
throw new LockedAccountException(user.getName+"被锁定");
}
ShiroUser principal = new ShiroUser;
String userInfo = user.getName+"("+user.getRole.getName+")";
principal.setUserInfo(userInfo);
principal.setAuthorities(user.getRole.getAuthorities);
Object hashedCredentials = user.getPassword;
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt);
String realmName = getName;
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,hashedCredentials, credentialsSalt,realmName);
public class ShiroUser{
//userName(roleName)
private String userInfo;
private List
public List
return authorities;
}
public void setAuthorities(List
this.authorities = authorities;
}
public String getUserInfo {
return userInfo;
}
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
* 初始化 使用MD5加密
*/
@PostConstruct
public void initCredentialsMatcher{
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher;
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
// 加密1024次
hashedCredentialsMatcher.setHashIterations(1024);
//
this.setCredentialsMatcher(hashedCredentialsMatcher);
Main方法生成salt 和password
// 利用shiro提供的随机数生成类、生成随机数,用于盐值加密
SecureRandomNumberGenerator secureRandomNumberGenerator =
new SecureRandomNumberGenerator;
String str = secureRandomNumberGenerator.nextBytes.toBase64;
System.out.println(str);//
String algorithmName = "MD5";
Object source = "123456";
//盐值 NWJtcFg3VFNtNEdEWTh6UUtoSTRkdz09
ByteSource salt = ByteSource.Util.bytes(str);
int hashIterations = 1024;
Object result = new SimpleHash(algorithmName,source,salt,hashIterations);
System.out.println(result);//数据库中密码 b9aa43cfb15649c932ac647df54101a7
LoginController.java
@RequestMapping(value = "/login",method = RequestMethod.POST)
private String login(HttpServletRequest request,Modelmodel,
@RequestParam(name = "username",required = false) String username, @RequestParam(name = "password",required = false) String password, RedirectAttributes attributes){
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
//usernamePasswordToken.setRememberMe(false);
Subject subject = SecurityUtils.getSubject;
String message = null;
if(!subject.isAuthenticated){
try {
subject.login(usernamePasswordToken);
} catch (UnknownAccountException ex) {//用户名没有找到
//ex.printStackTrace;
message = "用户名不存在";
} catch (IncorrectCredentialsException ex) {//用户名密码不匹配
// ex.printStackTrace;
message = "用户名和密码不匹配";
}catch (LockedAccountException lae) {// 用户被锁定
//lae.printStackTrace;
message = "用户被锁定";
}catch (AuthenticationException e) {//其他的登录错误
e.printStackTrace;
}
if(message!=null){
attributes.addFlashAttribute("message", message);
return "redirect:/shiro-login";
return "redirect:/success";
}
基于注解的权限设置
在controller list方法上加上 @RequiresRoles(value={"admin"}) 说明此方法需要有admin角色的用户才可以操作。
@RequiresRoles(value={"admin"})
@RequestMapping(value = "/list", method= RequestMethod.GET)
public String list(Model model, HttpServletRequest request){
List
model.addAttribute("list", userList);
return "user/userList";
}
我们用两个用户来测试
可以看到admin用户可以访问list页面,而gx因为没有admin的角色,访问失败。
附:数据库关系图
总结:本文通过例子,简单实现了权限的控制,相比与spring secruity的复杂配置,shiro更加简单。
例子github:https://github.com/zhaoguoxin/gxshiro.git
相关推荐
手把手教你集成spring cloud + shiro微服务框架;用最少的工作量,改造基于shiro安全框架的微服务项目,实现spring cloud + shiro 框架集成。博客地址:...
本指南将详细探讨Shiro与Spring Web项目集成的过程,并分析Shiro在其中的作用和集成的关键点。 ### 1. Shiro与Spring框架的整合 Shiro与Spring Web项目的整合,首先需要在Spring项目中整合Shiro。整合的过程可以...
标题 "Shiro+SpringMVC+Spring集成" 涉及的是在Web开发中整合Apache Shiro、Spring MVC和Spring框架的过程。这三个组件都是Java Web开发中的重要工具,Shiro负责安全认证和授权,Spring MVC处理MVC模式的实现,而...
在这个项目中,Spring负责整体架构的管理,包括依赖注入、AOP(面向切面编程)以及与Shiro和Redis的集成。 **Shiro与Spring的集成** 将Shiro与Spring结合,可以利用Spring的IOC容器管理Shiro的组件,如Realm(领域...
而 Apache Shiro 是一个强大且易用的 Java 安全框架,提供了认证、授权、加密和会话管理功能,可以非常方便地与 Spring Boot 结合使用,为我们的应用程序提供安全控制。 在 Spring Boot 中集成 Shiro,主要涉及以下...
总的来说,Apache Shiro与Spring的集成可以让我们在Spring的环境中充分利用Shiro的安全功能,为应用程序提供全面的安全保障。通过理解和实践这些知识点,开发者可以构建更加安全可靠的Java应用。
Apache Shiro 和 Spring 的集成是企业级 Java 应用中常见的安全框架组合,它们共同为应用程序提供用户认证、授权和会话管理等功能。Shiro 是一个轻量级的安全框架,而 Spring 则是一个全面的后端开发框架。下面将...
总的来说,Spring、SpringMVC和Shiro的集成为空框架提供了一个坚实的基础,开发者可以在此基础上快速搭建企业级应用,提高开发效率并保证系统的安全性。理解这三个框架的核心概念和它们之间的协作方式,对于Java Web...
适用于spring集成的javaweb环境
1. **Spring与Shiro的集成**:讲解如何在Spring应用中引入Shiro,包括配置Shiro的依赖、设置Shiro的过滤器链以及Spring与Shiro的Bean配置。 2. **身份认证**:介绍Shiro的Subject、Realms和CredentialsMatcher等...
Spring Boot 集成 Shiro 和 CAS 本文将详细介绍 Spring Boot 集成 Shiro 和 CAS 的知识点,帮助读者了解 Shiro 和 CAS 的概念、使用方法,以及它们在 Spring Boot 中的集成方式。 Shiro 介绍 Shiro 是一个开源的 ...
shiro简单集成spring
5. 集成 Session 管理:Shiro 可以与 Spring Session 集成,实现分布式会话管理,尤其在微服务环境中。 四、Shiro 缓存处理 为了提高性能,Shiro 支持缓存机制,可以在认证和授权过程中减少对数据库的访问。常见的...
Apache Shiro 和 Spring MVC 是两个在 Java Web 开发中广泛使用的框架。Shiro 主要负责应用程序的...了解每个部分的作用和配置方式,有助于更好地理解和掌握 Shiro 与 Spring MVC 的集成,从而在实际项目中灵活运用。
5. **Shiro与Spring整合**: 使用Spring的DelegatingFilterProxy来代理Shiro的Filter,以便在Spring环境下运行。 6. **Shiro API使用**: 在业务代码或控制器中,可以调用Subject的登出、认证、授权等方法。 **SSM与...
通过学习和实践"spring-shiro整合",开发者不仅可以掌握Web安全框架的使用,还能深入理解Spring MVC和MyBatis的集成,提升项目开发能力。在实际项目中,这样的整合可以帮助我们快速构建出健壮、安全的Web应用。
本篇文章将深入探讨如何在Spring Boot项目中集成并使用Shiro,为你的Web应用构建稳固的安全防护。 一、Shiro简介 Apache Shiro是一个轻量级的安全管理框架,它主要处理身份验证(Authentication)、授权...
它与Spring核心容器紧密集成,可以方便地注入依赖,支持AOP(面向切面编程),并提供事务管理等服务。 **Spring**: Spring框架是Java企业级应用开发的核心框架,它包含了IoC(Inversion of Control,控制反转)和DI...
在"ShiroSpring"这个项目中,我们看到它与Spring框架集成,这是企业级应用开发中常见的做法,以便更好地管理和控制应用的安全性。下面我们将深入探讨Shiro和Spring集成的关键知识点。 1. **Shiro基础概念**: - **...
**Spring Boot与Shiro集成详解** 在Web应用开发中,权限管理和用户认证是不可或缺的部分。Spring Boot以其便捷的集成性和强大的功能,已经成为Java领域最受欢迎的框架之一。而Apache Shiro则是一个轻量级的安全框架...