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.没登陆:

Shiro添加自己的Filter

2.登录 : 

Shiro添加自己的Filter

将返回的uuid设置到header中

Shiro添加自己的Filter

整合shiro可以参考:http://blog.****.net/a295277302/article/details/77454119

ShiroFilterFactoryBean源码及拦截原理深入分析:http://blog.****.net/u012345283/article/details/44199791