1. Shiro简介
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能:
认证(Authentication):用户身份识别,常被称为用户“登录”,判断用户是否登陆,如果未登陆,则拦截其请求
授权(Authorization):访问控制。当用户登陆后,判断其身份是否有权限访问相应的资源,如果没有权限则拦截
密码加密(Cryptography):保护或隐藏数据防止被偷窃。将MD5进行二次封装,让其更加容易使用。注意MD5不可逆运算
会话管理(Session Management)
Shiro内置过滤器
anon | org.apache.shiro.web.filter.authc.AnonymousFilter |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter |
port | org.apache.shiro.web.filter.authz.PortFilter |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter |
ssl | org.apache.shiro.web.filter.authz.SslFilter |
user | org.apache.shiro.web.filter.authc.UserFilter |
这些过滤器分为两组:
认证过滤器:anon(不认证也可以访问),authcBasic, authc(必须认证后才可
访问)
授权过滤器:perms(指定资源需要哪些权限才可以访问),Roles, ssl,rest, port
在maven的web子模块中加applicationContext_shiro.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--安全管理器: shiro的核心,认证、授权、回话、缓存 -->
<property name="securityManager" ref="securityManager" />
<!-- 使用自定义的过滤器 -->
<property name="filters">
<map>
<!--如果key值与默认的相同时会替换掉 -->
<entry key="perms" value-ref="myPerms"></entry>
</map>
</property>
<!--如果没有登录 就跳转到登录页面 -->
<property name="loginUrl" value="/login.html" />
<!--如果用户没有权限 就跳转到错误页面 -->
<property name="unauthorizedUrl" value="/error.html" />
<!--过滤链 拦截规则 -->
<property name="filterChainDefinitions">
<value>
#1、anon 匿名
#2、perms 授权
#3、authc 认证
/error.html = anon
/login.html = anon
/goodstype.html=perms["商品类型"]
/goods.html=perms["商品"]
/dep.html=perms["部门"]
/emp.html=perms["员工"]
/orders.html=perms["采购订单查询","我的采购订单","采购审核","采购确认","采购入库","销售订单查询","我的销售订单","销售订单出库"]
/orders_*=perms["采购订单查询","我的采购订单","采购审核","采购确认","采购入库","销售订单查询","我的销售订单","销售订单出库"]
/storedetail.html=perms["商品库存"]
/storeoper.html=perms["库存变动记录"]
/supplier.html=perms["供应商管理","客户管理"]
/store.html=perms["仓库"]
/*.html = authc
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="erpRealm"></property>
</bean>
<bean id="myPerms" class="com.baidu.erp.filter.MyAuthorizationFilter"></bean>
<bean id="erpRealm" class="com.baidu.erp.realm.ErpRealm">
<property name="empBiz" ref="empBiz"></property>
<property name="menuBiz" ref="menuBiz"></property>
</bean>
<!-- 启动shiro注解 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" >
<!-- 默认使用JDK代理 ,如被代理类没有实现接口,必须使用下列配置开启 cglib代理 -->
<property name="proxyTargetClass" value="true" />
</bean>
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- 对安全管理器 增强代码 , spring 后处理器 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>
创建一个自定义授权过滤器
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
realm的创建:
/**
* 自定义ream,实现认证与授权
* @author Eric
*
*/
public class ErpRealm extends AuthorizingRealm {
private IEmpBiz empBiz;
private IMenuBiz menuBiz;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//授权 告诉当前用户拥有的权限名称
SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
Emp loginUser = (Emp)principals.getPrimaryPrincipal();//拿主事者
//用户所拥有的权限
List<Menu> menuList = menuBiz.getMenusListByEmpuuid(loginUser.getUuid());
//授权
for(Menu m : menuList){
//加入权限名称
sai.addStringPermission(m.getMenuname());
}
//sai.addStringPermission("采购订单查询");
/*sai.addStringPermission("我的采购订单");
sai.addStringPermission("采购确认");*/
return sai;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//得到登陆令牌
UsernamePasswordToken upt = (UsernamePasswordToken)token;
//获取登陆用户名
String username = upt.getUsername();
//登陆密码
String pwd = new String(upt.getPassword());
Emp emp = empBiz.findByUsernameAndPwd(username, pwd);
if(null != emp){
//1: 主事者,主角,登陆用户
//2: 凭证, 密码
//3: realm的名称
return new SimpleAuthenticationInfo(emp,pwd,getName());
}
return null;
}
public void setEmpBiz(IEmpBiz empBiz) {
this.empBiz = empBiz;
}
public void setMenuBiz(IMenuBiz menuBiz) {
this.menuBiz = menuBiz;
}
}
Subject:正与系统进行交互的人,或某一个第三方服务。所有Subject实例都被绑定到(且这是必须的)一个SecurityManager上。
SecurityManager:Shiro架构的心脏,典型的Facade模式。用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当Shiro与一个Subject进行交互时,实质上是幕后的SecurityManager处理所有繁重的Subject安全操作。
Realms:本质上是一个特定安全的DAO。当配置Shiro时,必须指定至少一个Realm用来进行身份验证和/或授权。Shiro提供了多种可用的Realms来获取安全相关的数据。如关系数据库(JDBC),INI及属性文件等。可以定义自己Realm实现来代表自定义的数据源。