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增加以下依赖:
2. 在项目中增加shiro配置。在spring配置文件目录下新建spring-shiro.xml。内容如下:
/=anon
/template/main.jsp=user
/api/createApiUser**=perms[api:user:create]
/api/updateApiUser**=perms[api:user:update]
/api/*User*=perms[api:user:view]
/template/apiUserManage/**=perms[api:user:view]
/api/*Interface*=perms[api:user:interface]
/api/querySummaryData**=perms[api:data]
/template/apiSumData/**=perms[api:data]
/api/**=perms[api:*]
...
/**=anon
3、在web.xml中增加shiro filter的配置:
classpath*:applicationContext.xml,
classpath*:spring-*.xml //
...
org.springframework.web.filter.DelegatingFilterProxy
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
for (UserGroup g: gList) { //获取用户的组
log.info("method[doGetAuthorizationInfo] group<" + g.getName() + ">");
List
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" %>
who has permission can see