Shiro添加自己的Filter
因为前后端分离,添加了自己的过滤器,根据cookie判断传过来的uuid是否是登录的token
使用到了cache,稍后会加上源码也稍后上传
ShiroConfiguration
@Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { //这里设置了自己的过滤器 ShiroFilterFactoryBean shiroFilter = new CustomShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); shiroFilter.setLoginUrl("/auth.html"); shiroFilter.setUnauthorizedUrl("/403.html"); Map<String, String> filterMap = new LinkedHashMap<>(); //开放swagger资源 start filterMap.put("/v2/api-docs", "anon"); filterMap.put("/webjars/**", "anon"); filterMap.put("/swagger-resources/**", "anon"); filterMap.put("/swagger-ui.html", "anon"); //开放swagger资源 end filterMap.put("/api/**", "anon"); filterMap.put("/assets/**", "anon"); filterMap.put("/fonts/**", "anon"); filterMap.put("/maps/**", "anon"); filterMap.put("/api/_devops_/init", "anon"); filterMap.put("/configuration/ui", "anon"); filterMap.put("/configuration/security", "anon"); filterMap.put("/scripts/**", "anon"); filterMap.put("/styles/**", "anon"); filterMap.put("/auth.html", "anon"); filterMap.put("/index.html", "anon"); filterMap.put("/**", "authc"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; }
CustomShiroFilterFactoryBean
public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean { public static final String UUID_HEADER = "uuid"; private static final Pattern resourceSuffix = Pattern.compile("\\.\\w{1,15}$"); @Autowired private CacheService cacheService; @Override protected AbstractShiroFilter createInstance() throws Exception { // TODO Auto-generated method stub FilterChainManager manager = createFilterChainManager(); // Expose the constructed FilterChainManager by first wrapping // it in a // FilterChainResolver implementation. The AbstractShiroFilter // implementations // do not know about FilterChainManagers - only resolvers: PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); chainResolver.setFilterChainManager(manager); AbstractShiroFilter filter = new AbstractShiroFilter() { protected boolean pathMatches(String pattern, String path) { PatternMatcher pathMatcher = chainResolver.getPathMatcher(); return pathMatcher.matches(pattern, path); } protected boolean isRequestIgnored(ServletRequest request, ServletResponse response) { if (!manager.hasChains()) { return false; } String requestURI = WebUtils.getPathWithinApplication(WebUtils.toHttp(request)); SimpleNamedFilterList configuredFilter = null; Object anonFilter = null; for (String pathPattern : manager.getChainNames()) { // If the path does match, then pass on to the subclass implementation for specific checks: if (pathMatches(pathPattern, requestURI)) { configuredFilter = (SimpleNamedFilterList) manager.getChain(pathPattern); break; } } if(configuredFilter != null && !configuredFilter.isEmpty()){ anonFilter = configuredFilter.get(0); } if(anonFilter != null && anonFilter instanceof AnonymousFilter){ return true; }else{ HttpServletRequest hsr = (HttpServletRequest) request; // bypass resource if ("GET".equalsIgnoreCase(hsr.getMethod()) && (resourceSuffix.matcher(hsr.getRequestURI()).find() || "/".equals(hsr.getRequestURI()))){ return true; } return false; } } @Override protected WebSubject createSubject(ServletRequest request, ServletResponse response) { WebSubject ws = super.createSubject(request, response); if(isRequestIgnored(request,response)){ return ws; } if(request instanceof HttpServletRequest == false){ throw new RuntimeException("Inner error. The request is not a HttpServletRequest"); } HttpServletRequest hsr = (HttpServletRequest)request; String uuid = hsr.getHeader(UUID_HEADER); if (uuid != null && !uuid.isEmpty()) { String cache = cacheService.getValue(uuid); if(cache == null || cache == ""){ throw new AuthenticationException("uuid is illegal."); } String cache_uuid = cache.split("_")[0]; String userId = cache.split("_")[1]; String username = cache.split("_")[2]; String password = cache.split("_")[3]; UsernamePasswordToken token = new UsernamePasswordToken(username, password); if(!cache_uuid.equals(uuid)){ throw new AuthenticationException("uuid is illegal."); } try { ws.login(token); } catch (AuthenticationException e) { throw new RuntimeException("Inner error. Failed to login with shiro."); } } else { throw new ExceptionResponse("no "+UUID_HEADER+" header assigned"); } return ws; } }; filter.setSecurityManager((WebSecurityManager) getSecurityManager()); filter.setFilterChainResolver(chainResolver); return filter; } }
LoginController
@RequestMapping(value = "/login",method = RequestMethod.POST) @ApiOperation(value = "用户登录",notes = "根据用户名密码判断用户") @ApiImplicitParam(value = "Map",required = true,dataType = "Map") public Map<String,Object> login(@RequestBody Map<String, String> map) { Map<String , Object> resurt = new HashMap<>(); UsernamePasswordToken token = null; try { String username = map.get("username"); //sha256加密 String password = new Sha256Hash(map.get("password")).toHex(); User user = userService.findByUserName(username); // 账号不存在 if(user == null) { throw new ExceptionResponse("用户名不正确"); } //密码错误 if(!password.equals(user.getPassword())) { throw new ExceptionResponse("密码不正确"); } //账号禁用 if("0".equals(user.getStatus())){ throw new ExceptionResponse("用户已被禁用,请联系管理员"); } Subject subject = ShiroUtils.getSubject(); token = new UsernamePasswordToken(username, password); String uuid = UUIDGenerator.creatUUID(); resurt.put("uuid",uuid); cacheService.setValue(uuid,uuid + "_" + user.getId() + "_" + user.getUsername() + "_" + user.getPassword()); subject.login(token); }catch (Exception e){ System.out.println(e); } return resurt; }
测试:
1.没登陆:
2.登录 :
将返回的uuid设置到header中
整合shiro可以参考:http://blog.****.net/a295277302/article/details/77454119
ShiroFilterFactoryBean源码及拦截原理深入分析:http://blog.****.net/u012345283/article/details/44199791