为什么自定义Shiro的拦截器
Shiro自带的拦截器,一个请求只能赋予一个角色或者一个组合角色。
例如:
filterChainDefinitionMap.put("/user/*","roles[user,admin]"); 表示只有同时获得user和admin的角色才能访问/user/*
但是实际中,需要/user/* 的请求user和admin角色都可以访问,那么就需要自定义拦截器
怎么自定义Shiro的拦截器
默认的拦截器
所有的拦截器都继承了AccessControlFilter类
继承了AccessControlFilter类的拦截器有下图中的几种:
默认使用的拦截器是:RolesAuthorizationFilter
在默认的拦截器中,roles[user,admin] 表示user加上admin的组合角色
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue;
if (rolesArray == null || rolesArray.length == 0) {
//no roles specified, so nothing to check - allow access.
return true;
}
Set<String> roles = CollectionUtils.asSet(rolesArray); //将所有的权限加起来的组合权限
return subject.hasAllRoles(roles);
}
CollectionUtils.asSet()方法
public static <E> Set<E> asSet(E... elements) {
if (elements == null || elements.length == 0) {
return Collections.emptySet();
}
if (elements.length == 1) {
return Collections.singleton(elements[0]);
}
LinkedHashSet<E> set = new LinkedHashSet<E>(elements.length * 4 / 3 + 1);
Collections.addAll(set, elements);
return set;
}
自定义拦截器
//自定义Shiro过滤器
public class RoleFilter extends RolesAuthorizationFilter {
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
final Subject subject = getSubject(request, response);
final String[] rolesArray = (String[]) mappedValue;
if (rolesArray == null || rolesArray.length == 0) {
// 无指定角色时,无需检查,允许访问
return true;
}
for (String roleName : rolesArray) {
if (subject.hasRole(roleName)) {
return true;
}
}
return false;
}
}
设置拦截器为自定义的拦截器
@Bean("getShiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(defaultWebSecurityManager);
//自定义拦截器类型
//import javax.servlet.Filter;
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("roles", new RoleFilter());
//设置拦截器为自定义的拦截器
bean.setFilters(filterMap);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/user/*","roles[user,admin]");
filterChainDefinitionMap.put("/admin/*","roles[admin]");
// 设置过滤器
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//设置登录的请求 可以是路由也可以是压面
bean.setLoginUrl("/common/toLogin");
//设置未授权的请求 未授权-->未授权页面
bean.setUnauthorizedUrl("/common/toLogin");
return bean;
}
注意点
注意自己在授权时 是授予Role还是授予Perms
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前登录对象
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal(); //得到当前对象
//如果当前对象不为空 进行授权操作
if(currentUser!=null){
//设置当前用户的权限
//info.addStringPermission(currentUser.getPerms()); //授予perm
info.addRole(currentUser.getRole()); //赋予Role
}
return info;
}