Shiro快速入门 —— 2.拦截器

本系列博文目录:http://www.javashuo.com/article/p-ewndobct-kn.htmljava

 

ShiroFilter拦截器是整个Shiro的入口,用于拦截须要安全控制的请求并进行处理。ajax

shiro封装了不少不一样用途的拦截器,这里只介绍几个比较经常使用的拦截器,更详细介绍能够参考博文spring

《第八章 拦截器机制——跟我学Shiro》:http://jinnianshilongnian.iteye.com/blog/2025656安全

 

登陆拦截器(FormAuthenticationFilter)

因为此拦截器常常须要继承并重写里面的方法,来扩展本身的登陆拦截规则,因此会进行详细介绍。app

 

等录拦截器主要有两个做用框架

一、拦截登陆表单提交的路径(在拦截器工厂中配置)。jsp

    建立登陆认证所须要的Token令牌,并进入登陆认证流程。ide

二、拦截要求登陆才能够访问的路径时(在拦截规则中配置)。url

    若是已经登陆则直接进入到要访问路径,若是未登陆则访问被拒绝并跳转到登陆页。spa

 

方法介绍

createToken():

此方法用于建立登陆认证令牌,令牌内存储了登陆认证时所需的数据。当咱们须要扩展shiro原有令牌的时候会重写此方法,将扩展的令牌字段存入令牌。最典型的例子就是在令牌中增长了验证码字段。(令牌会在其余章节另做介绍)

/**
     * 建立Token
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);//获取用户名 表单name:username
        String password = getPassword(request);//获取密码 表单name:password
        boolean rememberMe = isRememberMe(request);//获取是否记住我 表单name:rememberMe
        String captchaId = WebUtils.getCleanParam(request, "captchaId");//获取验证码id
        String captcha = WebUtils.getCleanParam(request, "captcha");//获取用户输入的验证码字符

        return new CaptchaAuthenticationToken(username, password,captchaId, captcha, rememberMe);//存入本身定义的包含验证码的Token
    }

 

onLoginSuccess():

登陆认证成功后的行为。此方法只有在进行登陆认证成功后访问一次。以后再访问页面时不会调用此方法。

 

onAccessDenied():

访问被拒绝后的行为。在拦截规则中指定须要登录后才能访问的路径,若是没有登陆则认为访问被拒绝。

此方法处理访问被拒绝后的逻辑,最多见的就是对于ajax访问拒绝的特殊处理。

此方法处理完成后,默认行为会跳转到登陆页(能够在拦截器工厂中配置 或 setLoginUrl方法设置登录页)。

这里要注意若是是登陆操做,拦截器会先拦截并断定为拒绝访问进入到此方法,而后再去进行建立Token和登陆认证等操做。

 

setLoginUrl():

设置登录页路径。默认/login.jsp,能够在拦截器工厂中配置 或 使用此方法重置。

访问被拒绝时咱们可使用此方法返回到其余登录页面,而不是以前的登陆页。

@Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        setLoginUrl("/otherlLogin");
        return super.onAccessDenied(servletRequest, servletResponse);
    }

 

getUsername():

得到登录用户名。表单name值必须是username。

getPassword():

得到登录密码。表单name值必须是password。

isRememberMe():

得到是否记住我。表单name值必须是rememberMe。

 

拦截器工厂类(ShiroFilterFactoryBean)

这个类用于spring框架中配置过滤器。

经过此工厂类能够很方便的配置拦截器的各类基本属性。

方法:

setSecurityManager:

必输。注入一个SecurityManager类,SecurityManager负责管理整个shiro核心验证功能。

 

setLoginUrl:

配置登陆页路径。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。

这里须要注意登陆页即便不配置拦截规则也必定会被authc拦截。

在这有一个事情比较坑,setLoginUrl所配置的路径便是页面的访问路径,同时又是登录表单提交的路径。页面访问使用的是GET方式提交,表单使用的是POST方式提交。

/**
     * LoginController中的内容
     */

    //根路径
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String loginForm() {
        return "redirect:login";
    }

    //登陆页面
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginInput(@ModelAttribute("message") String message) {
        //判断是否已经登陆 或 是否已经记住我
        if (SecurityUtils.getSubject().isAuthenticated() || SecurityUtils.getSubject().isRemembered()) {
            return "redirect:/home";
        } else {
            return "login";
        }
    }

    //登陆表单提交
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(HttpServletRequest request, RedirectAttributes redirectAttributes) {
       //登陆认证逻辑
    }

在这里说明一下若是不一致致使的现象

若是只配了页面的访问路径则,登陆时将不会触发shiro登陆拦截器。

若是只配了登录表单提交的路径则,拦截器判断为未登陆时将没法回到登陆页面。

 

setSuccessUrl:

配置登陆成功页路径。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。

 

setUnauthorizedUrl:

配置没有权限跳转的页面。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。

 

setFilterChainDefinitionMap:

设置拦截规则。拦截规则是经过一个Map进行导入的。

拦截规则写法详见“拦截规则”部分。

 

setFilters:

用于注入本身实现的拦截器类。自定义拦截器通常是继承了shiro原有拦截器并重写了部分方法。

 

一个spring boot配置文件中拦截器工厂类的例子:

/**
     * 得到拦截器工厂类
     */
    @Bean (name = "authenticationFilter")
    public AuthenticationFilter authenticationFilter() {
        return new AuthenticationFilter();
    }
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,AuthenticationFilter authenticationFilter) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);//设置SecurityManager,必输
        shiroFilterFactoryBean.setLoginUrl("/login");//配置登陆路径(登陆页的路径和表单提交的路径必须是同一个,页面的GET方式,表单的POST方式)
        shiroFilterFactoryBean.setSuccessUrl("/home");//配置登陆成功页路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");//配置没有权限跳转的页面

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/", "anon"); //无需登陆认证和受权就可访问的路径使用anon拦截器
        filterChainDefinitionMap.put("/home/**", "user");//须要登陆认证的路径使用authc或user拦截器
        filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//须要权限受权的路径使用perms拦截器
        filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms拦截器可同时使用
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//设置拦截规则

        Map<String, Filter> map = new HashMap<String, Filter>();
        map.put("authc", authenticationFilter);//自定义拦截器覆盖了FormAuthenticationFilter登陆拦截器所用的拦截器名authc
        shiroFilterFactoryBean.setFilters(map);//添加自定义拦截器

        return shiroFilterFactoryBean;
    }

 

拦截规则写法

拦截规则使用Map<String, String>将路径与拦截器的映射关系进行匹配。

形式如:

Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("<拦截路径>", "<拦截器名称>");

<拦截器路径>

拦截器路径是一个从根路径开始的url,并支持通配符。

登陆页即便不配置也必定会被authc拦截。

<拦截器名称>

是shiro内置拦截器的名称,也能够本身实现拦截器为其定义名称。

anon - 无需登陆认证和受权就可访问的路径使用anon拦截器

authc - 须要登陆认证的路径使用authc拦截器

user - 用户拦截器,用户已经登陆认证 或 已经记住我 的均可以经过。

(user拦截器会自动调用authc 拦截器,因此若是要使用记住我功能只配置user便可)

perms[role_name] - 须要权限验证的路径使用perms拦截器。中括号内为权限名称列表。

 

多个拦截器能够混合使用用逗号分隔

例子:

Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/", "anon"); //无需登陆认证和受权就可访问的路径使用anon拦截器
filterChainDefinitionMap.put("/home/**", "user");//须要登陆认证的路径使用authc或user拦截器
filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//须要权限受权的路径使用perms拦截器
filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms拦截器可同时使用
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//设置拦截规则
相关文章
相关标签/搜索