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

本系列博文目录:https://my.oschina.net/u/3452433/blog/907396

 

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

shiro封装了很多不同用途的拦截器,这里只介绍几个比较常用的拦截器,更详细介绍可以参考博文

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

 

登录拦截器(FormAuthenticationFilter)

由于此拦截器经常需要继承并重写里面的方法,来扩展自己的登录拦截规则,所以会进行详细介绍。

 

等录拦截器主要有两个作用

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

    创建登录认证所需要的Token令牌,并进入登录认证流程。

2、拦截要求登录才可以访问的路径时(在拦截规则中配置)。

    如果已经登录则直接进入到要访问路径,如果未登录则访问被拒绝并跳转到登录页。

 

方法介绍

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);//设置拦截规则

 

转载于:https://my.oschina.net/u/3452433/blog/895640

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值