• Shiro安全框架案例


    基于Shiro的用户认证(不包含授权)

    Spring整合Shiro

    shiro原理

    1.1   搭建环境

    1.1.1      web模块 pom.xml

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!--shiro核心包-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.2</version>
    </dependency>

    1.1.2  Web.xml配置

    <!-- Shiro Security filter  filter-name这个名字的值将来还会在spring中用到,本段代码原样粘贴,注意该过滤器是代理过滤器,它什么都不干,可以通过再Spring整合中配置相应的过滤器权限拦截器进行相应的过滤器拦截-->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
    <!--如果设置"targetFilterLifecycle"为true,则spring来管理Filter.init()和Filter.destroy();若为false,则这两个方法失效--> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

    1.1.3  Spring整合shiro  applicationContext-shiro.xml

     <description>Shiro与Spring整合</description>
    
        <!--安全管理器-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!-- 引用自定义的realm -->
            <property name="realm" ref="authRealm"/>
        </bean>
    
        <!-- 自定义Realm域的编写 -->
        <bean id="authRealm" class="此处为自定义Realm域的全限定类名">
            <!-- 注入自定义Realm域的密码比较器 -->
            <property name="credentialsMatcher" ref="customerCredentialsMatcher" ></property>
        </bean>
    
        <!-- 密码比较器:密码加密和比较 -->
        <bean id="customerCredentialsMatcher" class="自定义的证书匹配器所在的全限定类名"/>
    
        <!-- filter-name这个名字的值来自于web.xml中filter的名字 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"/>
            <!--登录页面  -->
            <property name="loginUrl" value="/login.jsp"></property>
            <!-- 登录失败后 跳转到未经授权的页面 -->
            <property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
            <!--过滤器链定义,此处为访问路径设置过滤器链-->
            <property name="filterChainDefinitions">
                <!-- /**代表下面的多级目录也过滤,等号后面的单词就是过滤器 -->
                <value>

    <!--如果该路径的用户不包含“模块管理”权限就禁止访问--> <!-- /system/module/list.do = perms["模块管理"] userLogin.do /userLogin* = anon mylogiin.jsp /mylogin* = anon --> /index.jsp* = anon /login.jsp* = anon /login* = anon /logout* = anon /css/** = anon /img/** = anon /plugins/** = anon /make/** = anon <!-- --> /** = authc /*.* = authc </value> </property> </bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 生成代理,通过代理进行控制 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"/> </bean> <!-- 安全管理器 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <aop:aspectj-autoproxy proxy-target-class="true"/>

    2.1 自定义realm

    /**
     * 自定义reamlm*/
    public class AuthRealm extends AuthorizingRealm {
       @Autowired
       private UserService userService;
       @Autowired
       private ModuleService moduleService;
       /**
        *  授权管理:授权
        */
       protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
          return null;
       }
       /**
        *  身份认证
        *      用于验证输入的用户名密码给,登录
        */
       protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
          //1.获取到用户界面输入的用户名和密码
          UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
          //2.获取用户出入的用户名和密码
          String username = upToken.getUsername();
          String password = new String(upToken.getPassword());
          //3.根据用户名查询用户对象
          User user = userService.findByUsername(username);
          if(user != null) {
             //第一个参数:安全数据(user对象)
             //第二个参数:密码(数据库密码)
             //第三个参数:当前调用realm域的名称(类名即可)
             SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
             return info;
          }
          return null;  //subject.login()方法的时候会抛出异常
       }
    }
    AuthorizingRealm抽象类中被重写的方法来源

    2.2 自定义密码比较 

    在spring与shiro的整合文件中已经将该类交给realm域中,所以直接重写方法doCredentialsMatch即可

    /**
     * 密码比较器
     */
    public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
    
       /**
        * 用户密码比较
        *      1.对用户输入的密码进行加密
        *      2.比较用户输入的密码和数据库密码是否一致
        * @param token  用户界面输入的邮箱和密码
        * @param info   安全数据:用户对象user
        *
        * 111111 + 固定值(加盐)  =  xxxxxx
        */
       public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
          //1.获取用户输入的密码
          UsernamePasswordToken upToken = (UsernamePasswordToken) token;
          String loginPassword = new String(upToken.getPassword());
          String email = upToken.getUsername();
          //2.对登录密码进行加密
          //加密:使用MD5加密
          String md5Paasword = Encrypt.md5(loginPassword, email);//密码,盐
    
          //info.getPrincipals();//获取安全数据,用户对象
          //获取数据库密码
          String dbPassword = (String)info.getCredentials();
    
          //true:登录成功,false:抛出异常
          return md5Paasword.equals(dbPassword);
       }
    }

     2.3 用户登录url映射

    //用户登录
    @RequestMapping("/login")
    public String login(String username,String password) {
    
        //1、通过shiro框架提供的SecurityUtils工具类获取Subject
        Subject subject = SecurityUtils.getSubject();
        //2、构造用户名密码的安全对象upToken
        UsernamePasswordToken upToken = new UsernamePasswordToken(username,password);
        //3、通过Subject的login()方法将安全对象交给shiro的安全管理器SecurityManager
        subject.login(upToken);
        //4、通过shiro获取用户对象主体,保存到session
        User user = (User) subject.getPrincipal(); //获取完全对象
        session.setAttribute("user",user);
        //5、查询菜单数据
        List<Module> moduleList = moduleService.findModuleByUserid(user.getId());
        session.setAttribute("modules",moduleList);
        return "home/main";
    }

     shiro学习推荐阅读》》》》》

     》》》shiro的权限管理的注解开发只需要一个注解代码

     /**
         *  RequiresPermissions:
         *      value : 权限名称(标识)
         *  如果具备此权限:进入方法
         *  不具备此权限:抛出异常
         */
        @RequiresPermissions("模块管理")
        @RequestMapping(value = "/list",name = "查询所有")
        public String list(@RequestParam(defaultValue = "1")int page,@RequestParam(defaultValue = "3")int size){
            PageInfo info = moduleService.findAll(page,size);
            request.setAttribute("page",info);
            return "system/module/module-list";
        }

    2.4   页面标签展示

    通过shiro标签控制页面按钮和菜单的显示

    2.4.1      引入标签库

    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

    2.4.2      控制显示

    <shiro:hasPermission name="删除部门">
        <button type="button" class="btn btn-default" title="删除" onclick='deleteById()'><i class="fa fa-trash-o"></i> 删除</button>
    </shiro:hasPermission>

    2.4 用户退出

    //退出
        @RequestMapping(value = "/logout",name="用户登出")
        public String logout(){
            SecurityUtils.getSubject().logout();   //登出
            return "forward:login.jsp";
        }

    shiro自动管理session,此处会将session中的用户信息清除。

    shiro获取当前用户的用户名

    Subject subject = SecurityUtils.getSubject();
    Object principal = subject.getPrincipal();

    点击查看SpringBoot整合Shiro

  • 相关阅读:
    并发编程学习笔记(15)----Executor框架的使用
    并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理
    并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理
    并发编程学习笔记(12)----Fork/Join框架
    并发编程学习笔记(11)----FutureTask的使用及实现
    并发编程学习笔记(10)----并发工具类CyclicBarrier、Semaphore和Exchanger类的使用和原理
    设计模式:代理模式
    设计模式:装饰模式
    设计模式:几大原则
    设计模式:策略模式(Strategy)
  • 原文地址:https://www.cnblogs.com/kitor/p/11281629.html
Copyright © 2020-2023  润新知