shiro理论详解:
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能:
认证 - 用户身份识别,常被称为用户“登录”;
授权 - 访问控制;
密码加密 - 保护或隐藏数据防止被偷窥;
会话管理 - 每用户相关的时间敏感的状态。
Shiro的三个核心组件:Subject, SecurityManager 和 Realms.
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
shiro实践部分:
与spring整合配置:
web.xml
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>*.do</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
spring-context-shiro.xml
在web.xml引入
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-context*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--自定义Realm 继承自AuthorizingRealm -->
<bean id="monitorRealm" class="com.drink.common.shiro.MonitorRealm"></bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--设置自定义realm -->
<property name="realm" ref="monitorRealm" />
</bean>
<!-- 过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"></property>
<property name="loginUrl" value="/login.jsp" />
<property name="successUrl" value="/index.jsp" />
<property name="unauthorizedUrl" value="/error.jsp" />
<!-- 路径过滤方式(原则) -->
<property name="filterChainDefinitions">
<value>
/login.do* = anon <!-- 不需要认证 -->
/index.do* = anon
/tree.do* = anon
/error.jsp*= anon
/*.do* = authc <!-- 需要认证 -->
</value>
</property>
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"
value="org.apache.shiro.SecurityUtils.setSecurityManager" />
<property name="arguments" ref="securityManager" />
</bean>
与springmvc集成,此配置要放在springmvc配置文件中:
<!-- 启用shiro为spring配置的bean注释,只运行在lifecycleBeanProcessor之后 注解必须放在mvc配置文件中 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<!-- 启用shrio授权注解拦截方式 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
代码部分:
创建MonitorRealm类并集成AuthorizingRealm
实现此类的两个方法:
doGetAuthorizationInfo —– 授权管理方法
doGetAuthenticationInfo —– 认证方法
认证管理方法实现:
//获取token
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//根据token用户名查询用户
SysUser sysUser = sysUserMapper.findByUsername(token.getUsername());
if(StringUtils.isNotEmpty(sysUser)){
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getUsername(), sysUser.getPassword().toCharArray(),getName());
return info;
}else {
throw new UnknownAccountException("没有该用户");
}
控制层用法:
//使用shiro登陆
Subject userSubject = SecurityUtils.getSubject();
//创建token,密码是char[]类型
UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getLoginName(), sysUser.getPassword().toCharArray());
// 记住用户信息
token.setRememberMe(true);
//认证方法
userSubject.login(token);
认证方法实现:
//创建认证类
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
String username = (String) super.getAvailablePrincipal(principalCollection);
//admin为超级管理员
if("admin".equals(username)){
//添加角色
simpleAuthorizationInfo.addRole("admin");
List<SysAuth> sysAuths = sysAuthMapper.findAll();
for (SysAuth sysAuth : sysAuths) {
//添加角色相对应的权限
simpleAuthorizationInfo.addStringPermission(sysAuth.getPermission());
}
}else {
SysUser sysUser = (SysUser) sessionUtils.getObj("user");
List<SysRole> sysRoles = sysRoleMapper.findRoleByUser(sysUser.getId());
for (SysRole sysRole : sysRoles) {
simpleAuthorizationInfo.addRole(sysRole.getName());
}
List<SysAuth> sysAuths = sysAuthMapper.findAuthByUser(sysUser.getId());
for (SysAuth sysAuth : sysAuths) {
simpleAuthorizationInfo.addStringPermission(sysAuth.getPermission());
}
}
return simpleAuthorizationInfo;
权限认证用法:
1、编码式实现:
SecurityUtils.getSubject().isAuthenticated()
SecurityUtils.getSubject().getPrincipals()
SecurityUtils.getSubject().hasRole(“角色名称”)
SecurityUtils.getSubject().isPermitted(“权限标志”)
2、注解式实现:
@ RequiresAuthentication
可以用户类/属性/方法,用于表明当前用户需是经过认证的用户。
@ RequiresGuest
表明该用户需为访客用户
@ RequiresPermissions
当前用户需拥有制定权限
@RequiresRoles
当前用户需拥有制定角色
@ RequiresUser
当前用户需为已认证用户或已记住用户
3、标签应用:
在使用Shiro标签库前,首先需要在JSP引入shiro标签:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
guest标签
验证当前用户是否为“访客”,即未认证(包含未记住)的用户
<shiro:guest>
Hi there! Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>
user标签
认证通过或已记住的用户
<shiro:user>
Welcome back John! Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>
authenticated标签
已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。
<shiro:authenticated>
<a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>
notAuthenticated标签
未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。
<shiro:notAuthenticated>
Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>
principal 标签
输出当前用户信息,通常为登录帐号信息
Hello, <shiro:principal/>, how are you today?
hasRole标签
验证当前用户是否属于该角色
<shiro:hasRole name="administrator">
<a href="admin.jsp">Administer the system</a>
</shiro:hasRole>
lacksRole标签
与hasRole标签逻辑相反,当用户不属于该角色时验证通过
<shiro:lacksRole name="administrator">
Sorry, you are not allowed to administer the system.
</shiro:lacksRole>
hasAnyRole标签
验证当前用户是否属于以下任意一个角色。
<shiro:hasAnyRoles name="developer, project manager, administrator">
You are either a developer, project manager, or administrator.
</shiro:lacksRole>
hasPermission标签
验证当前用户是否拥有制定权限
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>
lacksPermission标签
与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过
<shiro:hasPermission name="user:create">
<a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>