问题
在开发中,我们希望不同的角色权限可以调用同一个API接口,例如/user/**相关API既可以由拥有admin权限的角色调用,也可以由拥有student权限的角色调用,这时我们可能会有2种方案
方案一
filterMap.put("/user/**","roles[admin]");
filterMap.put("/user/**","roles[student]");
方案二
filterMap.put("/user/**","roles[admin,student]");
但实际上,以上方法均不可行,由于shiro的内置过滤器是顺序执行,方案一中的
roles[student]
会覆盖掉前面的
roles[admin]
,导致
admin
权限角色无法调用对应接口;而方案二则会导致两种权限的角色都无法进行调用,翻阅shiro自带的权限过滤器
RolesAuthorizationFilter
源码发现,用户需要拥有roleArray中全部权限才能调用对应接口。
shiro自带的权限过滤器
/**
* Filter that allows access if the current user has the roles specified by the mapped value, or denies access
* if the user does not have all of the roles specified.
*
* @since 0.9
*/
public class RolesAuthorizationFilter extends AuthorizationFilter {
//TODO - complete JavaDoc
@SuppressWarnings({"unchecked"})
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;
}
//需要用户拥有roleArray中全部权限才能调用对应接口(需重写代码)
Set<String> roles = CollectionUtils.asSet(rolesArray);
return subject.hasAllRoles(roles);
}
}
重写权限过滤器的isAccessAllowed
/**
* 自定义角色权限管理器
* roles[admin]->roles[admin,student]
*/
public class ShiroRoleFilter extends RolesAuthorizationFilter {
@Override
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;
}
//满足任一权限即可
for(String roleName : rolesArray) {
if(subject.hasRole(roleName)) {
return true;
}
}
return false;
}
}
ShiroConfig配置类部分代码
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(defaultWebSecurityManager);
Map<String, Filter> filters = bean.getFilters();
//添加自定义权限过滤器
filters.put("roles",new ShiroRoleFilter());
bean.setFilters(filters);
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/**","roles[admin,student]");
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}
版权声明:本文为weixin_47208793原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。