为此重写shiro的权限过滤器能帮助我们去实现自己的权限过滤规则,动态的改变权限,为角色增加和减去权限
shiro的过滤器类别
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.project.User.entity.Result;
import com.project.User.entity.SysMenuEntity;
import com.project.User.mapper.SysMenuDao;
import com.project.User.mapper.UserInfoMapper;
import com.project.User.service.Impl.SysMenuServiceImpl;
import com.project.User.service.SysMenuService;
import com.project.User.service.UserInfoService;
import com.project.config.sys.RedisPreloadData;
import com.project.utils.JWTUtils;
import com.project.utils.SpringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
@Component
public class CustomisedURLPathMatchingFilter extends PathMatchingFilter {
@Autowired
SysMenuService sysMenuService;
@Autowired
//将权限信息缓存到redis
RedisTemplate redisTemplate;
@Override
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletResponse.setCharacterEncoding("UTF-8");
String tokens = httpServletRequest.getHeader("Authorization");
if(sysMenuService==null){
sysMenuService = (SysMenuService) SpringUtils.getBean("SysMenuService");
}
if(redisTemplate == null){
redisTemplate = (RedisTemplate) SpringUtils.getBean("redisTemplate");
}
// 获取请求的地址URI
String requestURI = getPathWithinApplication(request);
if (requestURI == null || requestURI.trim().equals("")){
httpServletResponse.getWriter().write(JSON.toJSONString(Result.error(403,"无权限访问",null)));
return false;
}
Subject subject = SecurityUtils.getSubject();
if (!subject.isAuthenticated()) {
httpServletResponse.getWriter().write(JSON.toJSONString(Result.error(401,"未登录",null)));
return false;
}
ReleaseMap releaseMap = (ReleaseMap) SpringUtils.getBean("ReleaseMap");
Map passMap = releaseMap.getReleaseMap();
Set strings = passMap.keySet();
for(String url:strings){
if(url!=null){
if(requestURI.contains(passMap.get(url))){
return true;
}
}
}
String token = httpServletRequest.getHeader("Authorization");
Integer userid = JWTUtils.getIntUser(token, "userid");
List menuUrl = JSONObject.parseArray((String)
redisTemplate.opsForValue().get(RedisPreloadData.ROLE_URL+userid),SysMenuEntity.class);
if(menuUrl == null){
menuUrl = sysMenuService.getMenuUrl(userid);
}
for(SysMenuEntity entity:menuUrl){
if(entity.getUrl()==null || "".equals(entity.getUrl())){continue;}
if(requestURI.contains(entity.getUrl())){
return true;
}
}
httpServletResponse.getWriter().write(JSON.toJSONString(Result.error(403,"无权限访问",null)));
return false;
}
}
2.StringUtil.java获取加载好的bean
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtils.applicationContext == null){
SpringUtils.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static T getBean(Class clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static T getBean(String name,Class clazz){
return getApplicationContext().getBean(name, clazz);
}
}
3.完成 了过滤器的编写后,需在shiro的配置文件中shiroConfig.java加载该过滤器,下面贴出部分shiro的配置文件方法
@Bean()
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
// 添加自己的过滤器并且取名为jwt
//自定义权限拦截器roles
Map filterMap = new HashMap<>();
filterMap.put("jwt", new JWTFilter());
filterMap.put("roles", new CustomisedURLPathMatchingFilter());
factoryBean.setFilters(filterMap);
Map filterRuleMap = new HashMap<>();
filterRuleMap.put("/**", "noSessionCreation,jwt,roles");
// 访问401和404页面不通过我们的Filter
filterRuleMap.put("/404", "anon");
filterRuleMap.put("/druid/**", "anon");
filterRuleMap.put("/swagger-ui.html/**", "anon");
filterRuleMap.put("/webjars/**", "anon");
filterRuleMap.put("/swagger-resources/**", "anon");
filterRuleMap.put("/configuration/security", "anon");
filterRuleMap.put("/configuration/ui", "anon");
filterRuleMap.put("/v2/api-docs", "anon");
filterRuleMap.put("/land/common/kaptcha", "anon");
filterRuleMap.put("/land/login", "anon");
filterRuleMap.put("/land/logout", "anon");
factoryBean.setFilterChainDefinitionMap(filterRuleMap);
return factoryBean;
}
注意shiro配置文件中map的拦截或放行顺序
看完整实例代码
码云:https://gitee.com/hydrogenated-oxygen/erpshiro
欢迎指正不足,共同进步



