Springboot 集成Shiro自定义Filter

网上自定义Filter的实现很多,这里我提供一种Springboot在代码中的实现。

Shiro提供的Filter我这里不一一介绍了,一般基于web会话的都是使用authc(这是FormAuthenticationFilter)。根据我无状态的登陆需求,选择了AccessControlFilter,网上也有说这个是最被广泛使用的,具体还是看自己需求吧。

Filter代码:

/**
 * @author Created by pangkunkun on 2017/11/18.
 */
public class MyAccessControlFilter extends AccessControlFilter {

    private static final Logger log= LoggerFactory.getLogger(MyAccessControlFilter.class);


    /**
     *
     * 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
     * (感觉这里应该是对白名单(不需要登录的接口)放行的)
     * 如果isAccessAllowed返回true则onAccessDenied方法不会继续执行
     * 这里可以用来判断一些不被通过的链接(个人备注)
     * * 表示是否允许访问 ,如果允许访问返回true,否则false;
     * @param servletRequest
     * @param servletResponse
     * @param object 表示写在拦截器中括号里面的字符串 mappedValue 就是 [urls] 配置中拦截器参数部分
     * @return
     * @throws Exception
     * */
    @Override
    public boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object object) throws Exception{
//        Subject subject = getSubject(servletRequest,servletResponse);
//        String url = getPathWithinApplication(servletRequest);
//        log.info("当前用户正在访问的 url => " + url);
//        log.info("subject.isPermitted(url);"+subject.isPermitted(url));
        return false;
    }

    /**
     * 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
     * onAccessDenied是否执行取决于isAccessAllowed的值,如果返回true则onAccessDenied不会执行;如果返回false,执行onAccessDenied
     * 如果onAccessDenied也返回false,则直接返回,不会进入请求的方法(只有isAccessAllowed和onAccessDenied的情况下)
     * */
    @Override
    public boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception{
        System.out.println("onAccessDenied");
        String username=request.getParameter(Constant.CRS_KEY);
        String signature=request.getParameter(Constant.SIGNATURE);

        String type=request.getParameter("type");

        //TODO 通过其它参数验证signature的正确性
        String digestValue=MD5Utils.MD5SendParame(signature);

        MyUsernamePasswordToken token=new MyUsernamePasswordToken(username,type, digestValue);

        Subject subject= SecurityUtils.getSubject();
        try {
            subject.login(token);
        }catch (Exception e){
            log.info("登陆失败");
            log.info(e.getMessage());
            onLoginFail(response);
            return false;
        }
        log.info("登陆成功");
        return true;
    }

继承这个filter 要实现两个方法,每个方法我都有给出解释。

isAccessAllowed这里,根据从网上找的实现,我感觉这个是类似白名单被放行的。如果有些特殊的url不需要登录,可以直接在这里通过,或者做其它的判断。当然,这里也可以砸Shiro配置中直接把相应的方法对应的filter栏设置成none,同样不会经过这里。

onAccessDenied是我主要逻辑功能处理的模块。在这里主要是UsernamePasswordToken这块,生成token对象后使用subject进行登录,以便后边方法中权限/角色的验证。

将自定义filter集成进shiro配置:

@Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
        log.info("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();

        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //自定义拦截器
        Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
        filtersMap.put("myAccessControlFilter", new MyAccessControlFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);

        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();

        filterChainDefinitionMap.put("/createPermission", "anon");
        filterChainDefinitionMap.put("/**", "myAccessControlFilter");


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
        //自定义拦截器
        Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
        filtersMap.put("myAccessControlFilter", new MyAccessControlFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);

这块代码是将自定义的拦截器设置进shiro的filterchain中。

filterChainDefinitionMap.put("/**", "myAccessControlFilter");

这里是设置使用自定义拦截器的url。我这里设置的是,如果没有其他拦截器定义的,都有走这个自定义的拦截器。

完整代码可以参考我前面文章Spring Boot集成无状态Shiro–内容详细介绍。

你可能感兴趣的:(SpringBoot,Shiro)