• (转) shiro权限框架详解06-shiro与web项目整合(上)


    http://blog.csdn.net/facekbook/article/details/54947730

    shiro和web项目整合,实现类似真实项目的应用

    本文中使用的项目架构是springMVC+mybatis,所以我们是基于搭建好的项目进行改造的。

    • 将shiro整合到web应用中
    • 登录
    • 退出
    • 认证信息在页面展现,也就是显示菜单
    • shiro的过滤器

    将shiro整合到web应用中

    数据库脚步

    sql脚步放到项目中,项目上传到共享的资源中,文章最后给出共享url。

    去除项目中不使用shiro实现认证的拦截器

        <!--拦截器 -->
        <!-- <mvc:interceptors> <mvc:interceptor> -->
        <!-- 用户认证拦截 -->
        <!-- <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean> 
            </mvc:interceptor> <mvc:interceptor> -->
        <!-- 授权拦截 -->
        <!-- <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.PermissionInterceptor"></bean> 
            </mvc:interceptor> </mvc:interceptors> -->
    

    添加shiro的jar包

    除了前面文章提到的shiro-core相关的jar包,还需要如下:

    • 与web整合的 shiro-web-1.2.3.jar
    • 与spring整合的 shiro-spring-1.2.3.jar
    • 与ehcache整合的 shiro-ehcache-1.2.3.jar

    在web.xml中配置shiro的filter

    在web系统中,shiro 也是通过filter进行拦截的。filter拦截后将操作交给filterChain(过滤器炼)。shiro中提供了多个filter,在栏目 shiro的过滤器 会全部介绍 
    在web中配置filter,如下:

        <!--shirofilter-->
        <!-- shiro过滤器,DelegatingFilterProxy通过代理模式将spring容器的bean和filter关联起来 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <!--设置true由servlet容器控制filter的生命周期-->
            <init-param>
                <param-name>targetFilterLifecycle</param-name>
                <param-value>true</param-value>
            </init-param>
            <!--设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean -->
            <init-param>
                <param-name>targetBeanName</param-name>
                <param-value>shiroFilter</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    新建applicationContext-shiro.xml文件

    内容下图:

        <!-- web.xml中shiro的filter对应的bean -->
        <!-- shiro的web过滤器 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <!-- logiUrl认证提交地址,如果没有认证通过将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
            <property name="loginUrl" value="/login.action" />
            <!-- 认证成功后统一跳转到first.action,建议不配置,shiro认证成功自动到上一个链接 -->
            <property name="successUrl" value="/first.action" />
            <!-- 通过unauthorizedUrl指定没有权限时跳转页面 -->
            <property name="unauthorizedUrl" value="/refuse.jsp" />
            <!-- 过滤器链定义,从上向下顺序执行,一般将/**放在最后面 -->
            <property name="filterChainDefinitions">
                <value>
                    <!--静态资源可以匿名访问 -->
                    /images/** = anon
                    /js/** = anon
                    /styles/** = anon
                    <!--登录验证码匿名访问-->
                    /validatecode.jsp = anon
                    <!--任何链接都可以不认证访问-->
                    /** = anon
                </value>
            </property>
        </bean>
    
        <!--securityManager安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="customRealm" />
        </bean>
    
        <!-- 自定义的realm -->
        <bean id="customRealm" class="cn.itcast.ssm.shiro.CustomRealm"/>
    • 1

    上面配置的CustomRealm 的内容和文章shiro权限框架详解05-shiro授权的CustomRealm一样。

    测试是否整合成功

    在界面输入CustomRealm 代码中的账号为 zhangsan 密码为 123 可以进入欢迎页面。 

    但是并没有菜单和相关用户信息

    登录功能

    原理

    由于登录使用的是 org.apache.shiro.web.filter.authc.FormAuthenticationFilter filter实现的,具体流程如下: 
    如果用户没有认证时,请求上面配置的loginUrl进行认证,用户的身份信息和密码提交到loginUrl,FormAuthenticationFilter拦截取出request中的username和password(参数的key是可以进行配置的,下一篇blog介绍)参数值。FormAuthenticationFilter调用realm传入一个token(包含username和password),realm根据username查询用户信息,如果查询不到,返回null,FormAuthenticationFilter向request域中填充一个参数,key为shiroLoginFailure 记录异常信息。如果不为空的话,返回AuthenticationInfo 类。

    修改登录页面

    由于FormAuthenticationFilter的身份信息和密码的请求参数的key默认是(username和password),修改login.jsp页面的账号和密码输入框name属性值,并注释掉验证码的代码。

    修改controller类

    修改LoginController 的 login 方法如下:

        @RequestMapping("/login")
        public String login(HttpServletRequest request)throws Exception{
    
            //如果登录失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
            String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
            if(exceptionClassName!=null){
                if(UnknownAccountException.class.getName().equals(exceptionClassName)){
                    throw new CustomException("账号不存在");
                }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){
                    throw new CustomException("用户名或密码错误");
                }else {
                    throw new Exception();//最终在异常处理器生成未知错误
                }
            }
            //此方法不处理登录成功(认证成功),shiro认证成功会自动跳转到上一个请求路径。
            //登录失败还到login页面
            return "login";
        }

    这个方法只有校验不通过的时候才会执行。真正的校验方法是在自定义的realm中,校验身份是否正确。

    修改认证拦截器

    将所有请求都改为需要认证才能访问的。

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <!-- logiUrl认证提交地址,如果没有认证通过将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
            <property name="loginUrl" value="/login.action" />
            <!-- 认证成功后统一跳转到first.action,建议不配置,shiro认证成功自动到上一个链接 -->
            <property name="successUrl" value="/first.action" />
            <!-- 通过unauthorizedUrl指定没有权限时跳转页面 -->
            <property name="unauthorizedUrl" value="/refuse.jsp" />
            <!-- 自定义filter配置 -->
            <property name="filters">
                <map>
                    <entry key="authc" value-ref="formAuthenticationFilter"/>
                </map>
            </property>
    
            <!-- 过滤器链定义,从上向下顺序执行,一般将/**放在最后面 -->
            <property name="filterChainDefinitions">
                <value>
                    <!--静态资源可以匿名访问 -->
                    /images/** = anon
                    /js/** = anon
                    /styles/** = anon
                    /validatecode.jsp = anon
    
                    <!-- /**=authc 表示所有的url都需要认证才能访问 -->
                    /** = authc
                </value>
            </property>
        </bean>

    验证登录功能

    在登录界面输入账号为 zhangsan 密码为 123 验证是否登录成功,然后输入错误的账号,控制台出现下面的异常信息: 
     
    如果输入密码错误: 
     
    异常信息和前面Java项目演示的一样。

    退出

    退出不需要我们自己实现,只要去访问一个退出的url(该url是可以不存在的)即可,由LogoutFilter filter处理,清除session。在applicationContext.xml配置logoutFilter

        <!-- web.xml中shiro的filter对应的bean -->
        <!-- shiro的web过滤器 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <!-- logiUrl认证提交地址,如果没有认证通过将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
            <property name="loginUrl" value="/login.action" />
            <!-- 认证成功后统一跳转到first.action,建议不配置,shiro认证成功自动到上一个链接 -->
            <property name="successUrl" value="/first.action" />
            <!-- 通过unauthorizedUrl指定没有权限时跳转页面 -->
            <property name="unauthorizedUrl" value="/refuse.jsp" />
            <!-- 自定义filter配置 -->
            <property name="filters">
                <map>
                    <entry key="authc" value-ref="formAuthenticationFilter"/>
                </map>
            </property>
    
            <!-- 过滤器链定义,从上向下顺序执行,一般将/**放在最后面 -->
            <property name="filterChainDefinitions">
                <value>
                    <!--静态资源可以匿名访问 -->
                    /images/** = anon
                    /js/** = anon
                    /styles/** = anon
                    /validatecode.jsp = anon
                    <!-- 请求logout.action地址,shiro去清除session -->
                    /logout.action = logout
                    <!-- /**=authc 表示所有的url都需要认证才能访问 -->
                    /** = authc
                </value>
            </property>
        </bean>

    删除原来的退出方法。

    菜单显示

    修改realm从数据库查询用户信息及用户拥有的菜单设置在AuthenticatorInfo中。具体代码如下:

        /**
         * 用于认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) 
                throws AuthenticationException {
            //第一步:通过token获取身份信息
            String userCode = (String) token.getPrincipal();
    
        if (!"zhangsan".equals(userCode)) {// 这里模仿查询不到
                return null;
            }
            String password = "123";
    
            //模拟数据activeUser就是用户身份信息
            ActiveUser activeUser = new ActiveUser();
            activeUser.setUserid("zhangsan");
            activeUser.setUsercode("zhangsan");
            activeUser.setUsername("张三");
    
            //查询菜单信息
            List<SysPermission> menus = null;
            try {
                menus = sysService.findMenuListByUserId(activeUser .getUsercode());
            } catch (Exception e) {
                e.printStackTrace();
            }
            activeUser.setMenus(menus);
    
            //如果查询到结果返回AuthenticationInfo
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(activeUser, password, "");
            return authenticationInfo;
        }
    • 1

    上面的代码通过模拟从数据库获取数据设置到ActiveUser中。

    修改FirstAction中的first方法

    修改代码将获取身份信息,并放入request域中用于页面显示。

        //系统首页
        @RequestMapping("/first")
        public String first(Model model)throws Exception{
    
            Subject subject =SecurityUtils.getSubject();
            ActiveUser activeUser =  (ActiveUser)subject.getPrincipal();
            model.addAttribute("activeUser", activeUser);
            return "/first";
        }

    测试

    在登录界面,账号输入 zhangsan , 密码输入 123 
    如果成功的话,将会看到如下页面。 

    shiro过滤器总结

    过滤器简称对应的Java类
    anon org.apache.shiro.web.filter.authc.AnonymousFilter
    authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
    authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
    perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
    port org.apache.shiro.web.filter.authz.PortFilter
    rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
    roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
    ssl org.apache.shiro.web.filter.authz.SslFilter
    user org.apache.shiro.web.filter.authc.UserFilter
    logout org.apache.shiro.web.filter.authc.LogoutFilter

    各个过滤器的介绍和作用:


    anon:例子/admins/**=anon 没有参数,表示可以匿名使用。


    authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数 。


    roles:例子 /admins/user/** =roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/** =roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。


    perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。


    rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method],其中method为post,get,delete等。


    port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString 
    是你访问的url里的?后面的参数。


    authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证


    ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https


    user:例如/admins/user/**=user没有参数表示必须存在用户, 身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查


    注: 
    anon,authcBasic,auchc,user是认证过滤器, 
    perms,roles,ssl,rest,port是授权过滤器

    blog的项目地址

    点击进入下载页面

  • 相关阅读:
    python logging模块
    python re模块
    python xml模块
    python json,pickle,shelve模块
    python os,sys模块
    python 临时添加环境变量
    python random模块
    python time模块
    python 装饰器的简单使用
    python学习之路(二)
  • 原文地址:https://www.cnblogs.com/telwanggs/p/7118151.html
Copyright © 2020-2023  润新知