shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
/static/** = anon
/login/** = anon
/common/** = anon
/admin/** = authc,roles[admin]
/* = authc
/** = authc
public class MyRealm extends AuthorizingRealm{
Logger log=Logger.getLogger(MyRealm.class);
@Autowired
private UserService userService;//这是自己实现的用户信息操作类,实现用户信息,用户角色信息、用户权限信息查询功能
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
UserInfo user = (UserInfo) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 查询角色信息
Collection roles = userService.findRoles(user);
info.addRoles(roles);
log.info("shiro获取用户所属角色列表:"+roles);
// 查询权限信息
Collection permissions = userService.findPermissions(user.getSystemuserid());
info.addStringPermissions(permissions);
log.info("shiro获取用户权限列表:"+permissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException{
//用户输入的用户名密码
String loginname= token.getPrincipal().toString();
Object password=token.getCredentials();
log.info("shiro正在处理尝试登录的用户信息:"+loginname+",密码:"+new String((char[])password));
//数据库中的用户信息
UserInfo user =userService.queryUserInfoByLoginName(loginname);
if(user==null||CommonUtil.isNull(user.getLoginusername(),user.getPassword(),user.getSystemuserid())){
return null;
}
log.info("shiro获取到当前用户尝试登录的真实数据:"+user.getLoginusername()+",密码:"+user.getPassword());
//数据库中的正确的账户信息
AuthenticationInfo accountInfo =new SimpleAuthenticationInfo(user, user.getPassword(),getName());
//自己获取密码验证器(由于shiro实现的密码校验方法是密码错误会直接抛异常,不采用,所以改成直接手动校验)
CredentialsMatcher matcher=getCredentialsMatcher();
if(matcher==null){
log.error("没有配置密码匹配器");
return null;
}
//校验密码
if(matcher.doCredentialsMatch(token,accountInfo)){
return accountInfo;//校验通过,返回账号信息
}
return null;
}
}
/**
* 自定义shiro密码匹配(密码是在md5散列值的基础上再次进行md5加盐操作,加盐值不保存在数据库,而是放在配置文件中)
* @author eguid
*
*/
public class MyCredentialsMatcher extends CodecSupport implements CredentialsMatcher {
private static final Logger log = LoggerFactory.getLogger(MyCredentialsMatcher.class);
protected Object getCredentials(AuthenticationToken token) {
return token.getCredentials();
}
protected Object getCredentials(AuthenticationInfo info) {
return info.getCredentials();
}
@Autowired
private CommonConfigs commonConfigs;
/**
* 验证密码
*
* @param tokenCredentials
* @param accountCredentials
* @return
*/
protected boolean equals(Object tokenCredentials, Object accountCredentials) {
if (log.isDebugEnabled()) {
log.debug("Performing credentials equality check for tokenCredentials of type ["
+ tokenCredentials.getClass().getName() + " and accountCredentials of type ["
+ accountCredentials.getClass().getName() + "]");
}
if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
if (log.isDebugEnabled()) {
log.debug("Both credentials arguments can be easily converted to byte arrays. Performing "
+ "array equals comparison");
}
byte[] tokenBytes = toBytes(tokenCredentials);
byte[] accountBytes = toBytes(accountCredentials);
return MessageDigest.isEqual(tokenBytes, accountBytes);
} else {
return accountCredentials.equals(tokenCredentials);
}
}
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = getCredentials(token);
Object accountCredentials = getCredentials(info);
String account=String.valueOf((char[])tokenCredentials);
if(commonConfigs.getMd5salt()==null){
if (log.isDebugEnabled()) {
log.debug("配置文件中的加盐值为空,无法进行密码匹配,请确认配置文件是否在指定位置或配置指定加盐值");
}
return false;
}
String saltaccount=MD5Util.getMD5(account, commonConfigs.getMd5salt());
if (log.isDebugEnabled()) {
log.debug("加盐后的密码:"+saltaccount);
}
return equals(accountCredentials, saltaccount.toCharArray());
}
}
@RequiresPermissions({"user:update:view"})//检查操作权限
@RequiresPermissions(value={"user:add","user:view"},logical=Logical.OR)//两个操作权限其中一个满足条件即可通过检查
@RequiresRoles({"admin"})//检查角色
@RequiresRoles(value={"debug","admin"},logical=Logical.OR)//两个角色其中一个角色满足条件即可
@RequiresAuthentication//检查是否通过shiro认证
@RequiresGuest//不需要验证
@RequiresUser//检查用户是否是当前系统中的用户
使用标签需要先导入shiro的标签库<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
默认调用Subject.getPrincipal()获取
相当于((User)Subject.getPrincipals()).getUsername()
把shiro注解放到springMVC的注解扫描之后(即放在springMVC容器中加载)
把上面的shiro直接扫描放到下面的servlet-context.xml中即可让shiro注解生效
appServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring/servlet-context.xml
2
appServlet
/