shiro:安全(权限)框架,
【用途】:1)验证用户
2)对用户执行访问控制,如: 判断用户是否拥有角色admin;判断用户是否拥有访问的权限
3)在任何环境下使用 Session API,可以使用多个用户数据源。例如一个是oracle用户库,另外一个是mysql用户库
4)单点登录(SSO)功能,“Remember Me”服务 ,类似购物车的功能,shiro官方建议开启
s【shiro的4大API】
Authentication —— 认证,用户身份识别,常被称为用户“登录”,who are you?
Authorization —— 授权,访问控制过程,决定“谁”访问“什么”,who can do what?
Session Management —— 会话管理,用户session管理器,用户相关的时间敏感的状态
Cryptography —— 密码加密,把JDK中复杂的密码加密方式进行封装,保护或隐藏数据防止被偷窥
shiro包含3个核心组件:Subject、SecurityManager和Realms
Subject 是与程序进行交互的对象,可以是人也可以是服务或者其他,通常就理解为用户。
所有Subject 实例都必须绑定到一个SecurityManager上。我们与一个 Subject 交互,
运行时shiro会自动转化为与 SecurityManager交互的特定 subject的交互。
SecurityManager 是 Shiro的核心,初始化时协调各个模块运行。当SecurityManager协调完毕,
SecurityManager 会被单独留下,且我们只需要去操作Subject即可,无需操作SecurityManager 。
Realms在 Shiro中作为应用程序和安全数据之间的“桥梁”或“连接器”。它获取安全数据来判断subject是否能够登录,
subject拥有什么权限。有点类似DAO。在配置realms时,需要至少一个realm。而且Shiro提供了一些常用的 Realms来连接数据源,
如LDAP数据源的JndiLdapRealm,JDBC数据源的JdbcRealm,ini文件数据源的IniRealm,properties文件数据源的PropertiesRealm等等。
我们也可以插入自己的 Realm实现来代表自定义的数据源。像其他组件一样,Realms也是由SecurityManager控制。
1. 引入shiro需要的包。使用maven的项目中,在pom.xml增加以下依赖:
<!-- shiro权限管理 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.1.0</version>
</dependency>
<!-- shiro权限管理 end -->
2. 在项目中增加shiro配置。在spring配置文件目录下新建spring-shiro.xml。内容如下:
<!-- Shiro权限管理配置 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- shiro通过一个filter控制权限-->
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login/execute.do" /> <!-- 登陆页 -->
<property name="successUrl" value="/index.jsp" /> <!-- 登陆成功之后跳转的页面 -->
<property name="unauthorizedUrl" value="/login/execute.do" /> <!-- 用户在请求无权限的资源时,跳转到这个url -->
<property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
</entry>
</util:map>
</property>
<property name="filterChainDefinitions"> <!-- 配置访问url资源需要用户拥有什么权限 配置的优先级由上至下-->
<value>
/=anon
/template/main.jsp=user
<!-- api用户信息 -->
/api/createApiUser**=perms[api:user:create] <!-- 权限可以用":"分级,如拥有api权限相当于拥有api*权限(父权限涵盖子权限) -->
/api/updateApiUser**=perms[api:user:update]
/api/*User*=perms[api:user:view]
/template/apiUserManage/**=perms[api:user:view]
<!-- api接口管理 -->
/api/*Interface*=perms[api:user:interface]
<!-- api统计数据 -->
/api/querySummaryData**=perms[api:data]
/template/apiSumData/**=perms[api:data]
/api/**=perms[api:*]
...
/**=anon
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="permissionsRealm" /> <!-- 自定义登陆及获取权限的源 -->
</bean>
<!-- shiro权限管理配置 end -->
3、在web.xml中增加shiro filter的配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext.xml,
classpath*:spring-*.xml //
</param-value>
</context-param>
...
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4、定义登陆及获取权限的源。
/**
* 认证实现类
*
* @author kexm
*
*/
@Service("permissionsRealm")
public class PermissionsRealm extends AuthorizingRealm {
@Autowired
private AccountDao accountDao;
@Autowired
private GroupDao groupDao;
private Account acc;
private static LogUtil log = LogUtil.getLogger(PermissionsRealm.class);
/**
* 用户权限源(shiro调用此方法获取用户权限,至于从何处获取权限项,由我们定义。)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
log.info("method[doGetAuthorizationInfo] begin.");
if (acc != null) {
if(acc.getAdminType() == 2){//超级管理员 始终拥有所有权限
info.addStringPermission("*");
return info;
}
try {
List<UserGroup> gList = accountDao.getUserGroups(acc.getLoginName());
for (UserGroup g: gList) { //获取用户的组
log.info("method[doGetAuthorizationInfo] group<" + g.getName() + ">");
List<Permission> pList = groupDao.getGroupPerms(g.getId());
for (Permission p: pList) { //获取组内权限
log.info("method[doGetAuthorizationInfo] perm<" + p.getName() + "," + p.getPermList() + ">");
String permList = p.getPermList();
if (permList != null && !"".equals(permList)) {
String[] perms = p.getPermList().split(",");
for (String perm: perms) {//分别放入容器 (权限以字符串形式呈现,如"api:data"等,和spring-shiro.xml中的配置相对应)
log.info("method[doGetAuthorizationInfo] add perm<" + perm + ">");
info.addStringPermission(perm);
}
}
}
}
return info;//将用户权限返回给shiro
} catch (Exception e) {
log.error("method[doGetAuthorizationInfo] e.message<" + e.getMessage() + "> e<" + e + ">", e);
}
}
return null;
}
/**
* 用户登录验证源(shiro调用此方法执行认证)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authtoken) throws AuthenticationException {
log.info("method[doGetAuthenticationInfo] begin.");
UsernamePasswordToken token = (UsernamePasswordToken) authtoken;
SimpleAuthenticationInfo authenticationInfo = null;
String userName = token.getUsername();
String password = new String(token.getPassword());
Login conf = DefaultConfigure.config.getLogin();
String MD5pwd = MD5Util.generateSignature(conf.getSalt(), password);
try {
if (userName != null && !"".equals(userName)) {
acc = accountDao.login(userName, MD5pwd);
}
if (acc != null) {
doGetAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
authenticationInfo = new SimpleAuthenticationInfo(token.getUsername(), token.getPassword(), getName());
return authenticationInfo;
}
} catch (Exception e) {
log.error("method[doGetAuthenticationInfo] acc<" + acc + "> message<" + e.getMessage() + "> e<" + e + ">",
e);
}
return null;
}
}
5、shiro中,使用subject管理用户。可以把subject理解为shiro存储用户信息的容器和操纵用户的工具。
有了前几步的配置,便可以使用以下代码登入登出,并享受shiro的url权限控制了。
//登入
UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
Subject user = SecurityUtils.getSubject();
user.login(token);
//使用shiro自带的session存储用户信息 独立于httpSession
Session ss = user.getSession().setAttribute("userInfo", acc);
//登出
SecurityUtils.getSubject().logout();
6、在页面中使用shiro标签。假如我们要让有权限的用户看到某些菜单或按钮,可以用以下方式。
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<shiro:hasPermission name="api:data">
who has permission can see
</shiro:hasPermission>
转载于:https://blog.51cto.com/wpei1314/1968887