• Spring集成Shiro使用小结


    shiro的认证流程

    认证流程

    Application Code:应用程序代码,由开发人员负责开发的
    Subject:框架提供的接口,代表当前用户对象
    SecurityManager:框架提供的接口,代表安全管理器对象
    Realm:可以开发人员编写,框架也提供一些,类似于DAO层,用于访问权限数据

    引入maven依赖

    
       <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-all</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
    
    

    配置web.xml

    
        <!-- 配置Spring框架提供的用于整合Shiro框架的过滤器   shiro 过滤器一定要保证 要先进入!!
            这个过滤器的名字必须与Spring配置文件中的ben配置id相同
        -->
    
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    
        </filter>
    
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    

    在Spring配置文件中配置shiro

    
    
        <!--shiro 配置方式-->
    
        <!--注册realm-->
        <bean id="myRealm" class="top.wintp.crud.service.MyRealm"/>
    
    
        <!--配置安全管理器-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="myRealm"/>
        </bean>
    
    
        <!--配置shiro过滤器工厂对象-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    
            <!--securityManager 注入安全管理器-->
            <property name="securityManager" ref="securityManager"/>
    
    
            <!--注入相关页面的访问URL-->
    
            <property name="loginUrl" value="/user/login.do"/>
            <!--<property name="successUrl"/>-->
            <property name="unauthorizedUrl" value="/user/unAuth.do"/>
    
    
            <!--
                注入URL拦截规则
            -->
            <property name="filterChainDefinitions">
                <value>
                    /static/** = anon
                    /user/login.do=anon
                    /user/loginUser.do=anon
                    /emp/findAll.do=perms["admin"]
                    /** = authc
                </value>
            </property>
    
        </bean>
    
    

    MyRealm

    package top.wintp.crud.service;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.realm.Realm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.List;
    
    import top.wintp.crud.dao.TUserMapper;
    import top.wintp.crud.entity.TUser;
    import top.wintp.crud.entity.TUserExample;
    
    /**
     * 类描述:
     * <p>
     * 作者:  pyfysf
     * <p>
     * qq:  337081267
     * <p>
     * CSDN:    http://blog.csdn.net/pyfysf
     * <p>
     * 个人博客:    http://wintp.top
     * <p>
     * 邮箱:  pyfysf@163.com
     * <p>
     * 时间:2018/8/22
     */
    public class MyRealm extends AuthorizingRealm {
    
        @Autowired
        private TUserMapper mTUserMapper;
    
    
        @Override
        protected AuthorizationInfo
        doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
            System.out.println("自定义realm授权方法");
    
        @Override
        protected AuthorizationInfo
        doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
            System.out.println("自定义realm授权方法");
            TUser user = (TUser) principalCollection.getPrimaryPrincipal();
    
            System.out.println(user.getUsername());
            System.out.println(user.getPassword());
    
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    
            authorizationInfo.addStringPermission("admin");
    
            //授权
            return authorizationInfo;
        }
    
    
        @Override
        protected AuthenticationInfo
        doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("自定义realm认证方法");
    
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    
            TUserExample tUserExample = new TUserExample();
            tUserExample.createCriteria().andUsernameEqualTo(token.getUsername());
            List<TUser> tUsers = mTUserMapper.selectByExample(tUserExample);
    
    
            if (tUsers != null && tUsers.size() > 0) {
    
                TUser tUser = tUsers.get(0);
    
    
                //简单认证信息对象
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(tUser, tUser.getPassword(), this.getName());
    
    
                //认证
                return authenticationInfo;
            } else {
                return null;
            }
    
        }
    }

    修改用户登录的方法

    @Service
    public class UserService {
    
        public boolean loginUser(TUser user) {
    
            String username = user.getUsername();
    
    
            //shiro执行过程  获取当前用户--subject -->然后获取securityManager(安全管理器)(login 登录)
            // 然后调用realm
    
            //获取当前用户对象 -- 未认证
            Subject subject = SecurityUtils.getSubject();
    
            UsernamePasswordToken token
                    = new UsernamePasswordToken(user.getUsername(), user.getPassword());
    
            try {
                subject.login(token);
    
    
                TUser resultUer = (TUser) subject.getPrincipal();
    
                System.out.println("登录成功");
    
                return true;
    
    
            } catch (Exception e) {
            //代表认证失败
                e.printStackTrace();
    
                return false;
            }
        }
    }

    常用过滤器配置简称

    注解式编程

    首先需要在Spring的配置文件中开启Shiro的注解支持:在applicationContext.xml中加入下面代码:

    
        <!--开启shiro 框架的注解支持-->
        <bean id="advisorAutoProxyCreator"
              class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
            <!--默认开启CGLIB代理-->
            <property name="proxyTargetClass" value="true"/>
        </bean>
    
        <!--配置切面  用于创建代理对象-->
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

    有了上面的配置,我们就可以在我们的代码中使用Shiro的注解进行权限控制了:

    
        @RequestMapping("/findAll")
       @RequiresPermissions("emp-check")
        public String findAll(Model model, @RequestParam(value = "pageNum", defaultValue = "1")
                Integer pageNum) {
    
            logger.info("请求开始>>>>>");
    
            //书写分页逻辑--在这里进行分页声明之后,后面紧跟的查询就是一个分页目标
            //第二个参数是指定每次查询几条数据
            PageHelper.startPage(pageNum, 5);
    
            //调用Service里面的方法进行使用
            List<Employee> allEmployees = mEmployeeService.findAll();
            //使用PageInfo来包装返回的数据--可以更好的管理分页逻辑
    
            //第二个参数是页面上最多显示几个页数,比如限制只显示5个那么就为1,2,3,4,5
            //2,3,4,5,6||||3,4,5,6,7
            PageInfo<Employee> employeePageInfo = new PageInfo<Employee>(allEmployees, 5);
    
            logger.info("数据为:" + employeePageInfo);
    
            logger.info("请求结束>>>>>");
    
            //存储数据,跳转界面
            model.addAttribute("employeePageInfo", employeePageInfo);
            return "list";
        }

    中途遇到的问题

    配置注解之后,没有起到任何作用。
    可能一:在你的spring的配置文件中忽略扫描Controller注解,然而你在Controller中使用了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到Spring-mvc.xml文件中。

    
        <!--扫描所有包-->
        <context:component-scan base-package="top.wintp.crud">
            <!--除了控制器 都进行注解扫描-->
            <context:exclude-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller"/>
    
        </context:component-scan>

    如果有上面的配置,那么spring将不会扫描到Controller注解

    可能二:在你的spring-mvc中仅仅只是扫描到了Controller注解,然而你在service层或者dao层用到了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到applicationContext.xml文件中。

      <context:component-scan base-package="top.wintp.crud" use-default-filters="false">
            <!--只扫描控制器即可-->
            <context:include-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller"/>
    
        </context:component-scan>

    建议:在Spring的主配置文件中和Springmvc的配置文件中都加入对shiro注解的支持。特别注意:如果两个配置文件中都配置了,注意其id不能相同

    在jsp中使用shiro提供的标签库

    一、引入标签库
    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    二、使用合适的标签在合适的位置进行使用

    例如:

    <shiro:hasPermission name="admin">
    
        <button class="btn btn-primary" id="btn_add_emp">新增</button>
        <button class="btn btn-danger btn_all_del">删除</button>
    </shiro:hasPermission>

    上述代码为,当当前用户具有admin的权限时,新增和删除按钮才会显示

  • 相关阅读:
    ※剑指offer系列51:二叉搜索树的第k个结点
    ※剑指offer系列50:序列化二叉树
    sqlserver添加表注释、字段注释
    3-实体数据模型与LINQ-where&OfType
    3-实体数据模型与LINQ-Select
    Jquery 在子页面上设置父页面元素的值
    开发注意事项
    函数的进阶
    文件操作的相关内容
    基本数据类型----dict
  • 原文地址:https://www.cnblogs.com/shaofeer/p/11154345.html
Copyright © 2020-2023  润新知