美文网首页程序员Java 杂谈SpringHome
SpringBoot:集成Shiro之拦截器配置

SpringBoot:集成Shiro之拦截器配置

作者: 神经骚栋 | 来源:发表于2018-09-12 17:10 被阅读13次

    前言


    前面的几篇博客都是说的用户如何认证,如何授权,那么用户认证授权之后,我们该如何使用这些信息呢?这里我们就需要使用到Shiro框架中的拦截器功能.通过拦截器功能实现用户权限和角色的应用,下面我们就来看一下我们如何使用拦截器实现用户权限认证的应用.

    拦截器分类说明


    在配置拦截器之前,我们需要先了解Shiro本身给我们提供的拦截器都有什么,都有着什么样的特点.下面我们就来用表格的形式来看一下各种拦截器的特点.

    简写(加粗为常用) 名称 优先级(1为最高) 说明 对应Java类
    anon 匿名拦截器 1 不需要登录就能访问,一般用于静态资源,或者移动端接口 org.apache.shiro.web.filter.authc.AnonymousFilter
    authc 登录拦截器 2 需要登录认证才能访问的资源 org.apache.shiro.web.filter.authc.FormAuthenticationFilter
    authcBasic Http拦截器 3 Http身份验证拦截器,非常用类型,不太了解 org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
    logout 登出拦截器 4 用户登出拦截器,主要属性:redirectURL退出登录后重定向的地址 org.apache.shiro.web.filter.authc.LogoutFilter
    noSessionCreation 不创建会话拦截器 5 调用 subject.getSession(false) 不会有什么问题,但是如果 subject.getSession(true) 将抛出 DisabledSessionException 异常 org.apache.shiro.web.filter.authc.NoSessionCreationFilter
    prems 权限拦截器 6 验证用户是否拥有资源权限 org.apache.shiro.web.filter.authc.PermissionsAuthorizationFilter
    port 端口拦截器 7 其主要属性: port(80) 如果用户访问该页面是非 80,将自动将请求端口改为 80 并重定向到该 80 端口 org.apache.shiro.web.filter.authc.PortFilter
    rest rest风格拦截器 8 rest 风格拦截器,自动根据请求方法构建权限字符串构建权限字符串;非常用类型拦截器 org.apache.shiro.web.filter.authc.HttpMethodPermissionFilter
    roles 角色拦截器 9 验证用户是否拥有资源角色 org.apache.shiro.web.filter.authc.RolesAuthorizationFilter
    ssl SSL拦截器 10 只有请求协议是https才能通过,否则你会自动跳转到https端口(443) org.apache.shiro.web.filter.authc.SslFilter
    user 用户拦截器 11 用户拦截器,用户已经身份验证 / 记住我登录的都可; org.apache.shiro.web.filter.authc.UserFilter

    我们通过上面的表格可以轻松的分别每一种拦截器的优先级,这样假设某个资源访问同时设置了两个或者多个拦截器,我们可以清楚的知道拦截器的执行顺序,从而方便我们进行一些操作.

    INI文件配置拦截器


    我曾经在SpringBoot:集成Shiro之INI配置篇说过[urls]模块.但是,说的不是太详细.在这个模块,我们就来详细的看一下如何使用INI文件的形式配置过滤器.

    在配置之前,我们还需要重述一下 拦截器的通配符的写法,如下所示.

    ?:匹配一个字符
    *:匹配零个或多个字符
    **:匹配零个或多个路径
    

    然后,我们看一下[urls]模块的示例.这里我只用到了一些常用的拦截器

    [urls]
    #不需要登录
    /login=anon
    /static/**=anon
    #需要登录
    /home=authc
    #需要角色
    /deleteUser = roles["superAdmin"]
    #需要用户权限
    /addUser = perms["user:create"]
    

    但是,我们发现一个问题,假设用户没有该权限和没有该角色,或者没有登录的时候,还有登出的时候,我们都需要给他们配置对应的重定向路径.这时候,我们就不能在[urls]模块中使用了,我们需要在[main]模块中进行各个情况路径的重定向设置了.示例代码如下所示.

    [main]
    #用户登录的地址
    authc.loginUrl = /login
    #用户没有对应角色的跳转重指向
    roles.unauthorizedUrl = /login
    #用户没有对应权限的跳转重指向
    perms.unauthorizedUrl = /login
    #用户登出的跳转重指向
    logout.redirectUrl = /login
    
    注意:INI文件中 [urls] 模块拦截顺序是从上往下依次执行.

    代码形式配置拦截器


    使用INI文件配置拦截器是较为简洁的配置形式,其实质就是通过Bean注入的形式配置拦截器 接下来我们看一下我们如何通过代码形式配置拦截器.

    由于是使用的SpringBoot:集成Shiro之自定义Realm实现认证授权项目中的代码配置,那么,我们就看一下上一节都配置了什么吧,我们配置了核心安全事务管理器 和自定义的权限登录器.代码如下所示.

    @Configuration
    public class ShiroConfiguration {
        //配置核心安全事务管理器
        @Bean(name="securityManager")
        public DefaultWebSecurityManager securityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) {
            DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
            manager.setRealm(myShiroRealm);
            return manager;
        }
        //配置自定义的权限登录器
        @Bean(name="myShiroRealm")
        public MyRealm authRealm() {
            MyRealm myShiroRealm=new MyRealm();
            return myShiroRealm;
        }
    }
    

    我们继续配置拦截器模块的代码.整体代码如下所示.

        @Bean(name="shiroFilter")
        public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
            ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
            bean.setSecurityManager(manager);
            //配置登录的url和登录成功的url以及验证失败的url
            bean.setLoginUrl("/login");
            bean.setSuccessUrl("/home");
            bean.setUnauthorizedUrl("/login");
            //配置访问权限
            LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
            filterChainDefinitionMap.put("/loginUser", "anon");
            filterChainDefinitionMap.put("/static/*", "anon");
            filterChainDefinitionMap.put("/logout*","anon");
            bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return bean;
        }
    

    比较过来,依然发现,使用INI文件形式配置拦截器要比代码形式更加简洁.

    拦截器的简单使用


    现在我们来拿/html/login = anon/html/home = authc以及设置重定向的authc.loginUrl = /html/login来简单说明一下,具体应该如何使用.

    我们想让SpringBoot项目支持Html格式的访问,那么我们需要在pom.xml文件中加入如下的Maven依赖.

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    

    同时,我们要在application.properties文件中配置如下信息.设置HTML的存放路径,

    spring.thymeleaf.prefix=classpath:/templates/
    spring.mvc.view.suffix=.html
    

    目录结构如下所示.

    然后,我们把ShiroConfiguration配置文件进行如下的配置.

    @Configuration
    public class ShiroConfiguration {
    
        @Bean(name="shiroFilter")
        public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
            ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
            bean.setSecurityManager(manager);
            //配置登录的url和登录成功的url以及验证失败的url
            bean.setLoginUrl("/index");
            bean.setSuccessUrl("/home");
            bean.setUnauthorizedUrl("/index");
            //配置访问权限
            LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
            filterChainDefinitionMap.put("/index", "anon");
            filterChainDefinitionMap.put("/home", "authc");
            filterChainDefinitionMap.put("/**","anon");
            bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return bean;
        }
    
        //配置核心安全事务管理器
        @Bean(name="securityManager")
        public DefaultWebSecurityManager securityManager() {
            DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
            return manager;
        }
    
    }
    
    

    我们在resources目录下创建两个html页面,一个login.html,一个home.html,其中代码如下所示.

    login

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户登录</title>
    </head>
    <body>
    
    <div style="text-align: center;margin-top: 100px; font-size: 20px;">用户登录界面</div>
    
    </body>
    </html>
    

    home

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页面</title>
    </head>
    <body>
    
    <div style="text-align: center;margin-top: 100px; font-size: 20px;">Home界面</div>
    
    </body>
    </html>
    

    然后我们需要编写两个接口来访问login.html和home.html.这里我创建了一个名为HtmlController的控制器.整体代码较为简单,这里就直接黏贴出所有代码了.如下所示.

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import java.util.Map;
    
    @Controller
    public class HtmlController {
    
        @RequestMapping(value = "/index",method = RequestMethod.GET)
        public String userLoginHtmlAction (){
            return "index";
        }
    
        @RequestMapping(value = "/home",method = RequestMethod.GET)
        public String userHomeHtmlAction (){
            return "home";
        }
    
    }
    

    然后我们就会猜想有如下情况出现,假设我们可以直接通过浏览器访问/html/login,那么我们会直接访问到login.html ,但是当我们访问/html/home的时候,由于我们没有进行用户登录认证(根本就没有做登录接口.😁),所以我们不可能通过认证,通过登录重指向,浏览器仍然会展示login.html 页面,下面我们就启动项目来验证一下.如下所示,拦截成功.

    结语(未完待续)


    Shiro的拦截器已经配置完成了,下一篇博客我们将来说一下如何在网页中使用权限管理标签,欢迎继续关注骚栋.

    Demo传送门

    相关文章

      网友评论

        本文标题:SpringBoot:集成Shiro之拦截器配置

        本文链接:https://www.haomeiwen.com/subject/dtmugftx.html