zoukankan      html  css  js  c++  java
  • Shiro快速入门

    1.什么是Shiro

    Shiro是Java的一个安全框架, 完成权限控制的任务.

    权限控制的基本功能: 认证(让系统知道你是谁); 授权(让系统知道你能做什么)
    权限控制常用的技术: 过滤器/拦截器, 或者使用代理模式
    权限控制的数据模型: 权限表-(多对多)-角色表-(多对多)-用户表

    shiri的组成

    shiro的调用流程

    Application code:应用程序代码
    Subject:当前用户
    SecurityManager:安全管理器,shiro框架的核心对象,管理各个组件
    Realm:获取权限信息, 决定subject的访问权限, 可以有多个

    2.Shiro的使用

    2.1登录

    Subject subject = SecurityUtils.getSubject();  
    UsernamePasswordToken token = new UsernamePasswordToken(username, password); 
    try{
        // 注意:登录不成功以抛异常的方式通知
        subject.login(token);   
    }catch (UnknownAccountException e) {
        // 没找到用户名
    }catch (IncorrectCredentialsException e) {
        // 用户名密码不匹配
    }catch (AuthenticationException e) {
        // 其他登录错误
    }
    if (subject.isAuthenticated()) {
        // 登录成功后, 取回认证时通过签名存储的对象
        User user = (User) subject.getPrincipal();
    }

    2.2 在realm里管理用户~权限

    public class MyRealm extends AuthorizingRealm {
        
      // 登录及认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 获得登录用的token UsernamePasswordToken token = (UsernamePasswordToken) token; // 获得封装的username String username = token.getUsername(); User user = userDao.findByUsername(username); if (null == user) { return null; } else { // 获得真正的password String password = user.getPassword(); // 创建简单认证对象, 返回给安全管理器 // 参数一:可放入任何对象的签名, 执行subject.login()方法后可从subject.getPrincipal()取回 // 参数二:封装真正的密码, 交由安全管理器比对 // 参数三:当前realm的名称 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, this.getClass().getSimpleName()); return info; } } // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 获得签名, 可做进一步查询 User user = (User) principals.getPrimaryPrincipal(); // 创建简单授权对象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //授予perms["keyword"] info.addStringPermission("staff"); //授予role["keyword"] info.addRole("staff"); return info; } }

    2.3 配置及管理访问目标~权限

    2.3.1 过滤器方式:

    web.xml

      <!-- shiro过滤器, 从spring工厂拿, beanname为"shiroFilter" -->
      <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>

    applicationContext.xml

      <!-- shiro: 自定义的realm -->
        <bean id = "userDefineRealm" class="com.zx.bos.shiro.UserDefineRealm"></bean>
        
        <!-- 二级缓存-->
        <bean id="ehCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
        </bean>
        
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <!-- realm需注册给安全管理器 -->
            <property name="realm" ref = "userDefineRealm"></property>
            <!-- 使用ehcache二级缓存, 没必要频繁查询权限 -->
            <property name="cacheManager" ref="ehCacheManager"></property>
        </bean>
        
        
        <!-- shiro使用方式1, 对URL进行控制  -->
        <bean id = "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!-- 注入安全管理器 -->
            <property name="securityManager" ref="securityManager"></property>
            <!-- 未登录时跳转到登录页面 -->
            <property name="loginUrl" value="/login.jsp"/>
            <!-- 登录成功页面 -->
            <property name="successUrl" value="/index.jsp"/>   <!-- 登录后跳转到登陆前被拦截的页面, 不跳转至此 -->
            <!-- 权限不足提示页面 -->
            <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"/>
            <!-- URL拦截规则 -->  <!-- 有先后顺序 从上往下匹配 -->
            <property name="filterChainDefinitions">
                <value>
                    /css/** = anon
                    /images/** = anon
                    /js/** = anon
                    /login.jsp* = anon   <!-- 后面带参数 -->
                    /validatecode.jsp* = anon
              /page_base_staff.action = roles["staff"] /userAction_login.action = anon
    /* = authc </value> </property> </bean>

    anon:可以匿名使用。
    authc:需要认证(登录)才能使用
    roles:可以带参数, 参数可以多个,例如roles["admin,guest"], 表示每个参数都通过才算通过
    perms:可以带参数, 参数可以多个,perms["user:add:*,user:modify:*"]
    port:port[8081]表示当请求的url的端口不是8081时跳转到schema://serverName:8081?queryParams
    user:必须存在用户,登录操作时不做检查

    2.3.2 注解方式:

        <!-- shiro使用方式2, 使用注解对方法进行控制. 不同于url方式权限不足时跳转界面,它直接抛出异常 -->
        <!-- 代理 -->
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
            <property name="proxyTargetClass" value="true"></property>   <!-- 使用cglib创建代理对象,  默认false用jdk动态代理 -->
        </bean>
        <!-- 切面类 -->
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"/>  
        </bean>

    注意捕获权限不足时抛出的异常. 如果在struts里需要配置

    struts.xml

    <global-results>
        <result name="unauthorizedUrl">/unauthorizedUrl.jsp</result>
    </global-results>
    <!-- 接收异常 -->
    <global-exception-mappings>
        <exception-mapping result="unauthorizedUrl" exception="org.apache.shiro.authz.AuthorizationException"></exception-mapping>
    </global-exception-mappings>
    例如:
    @RequiresRoles("rolename");
    void someMethod();
    @RequiresPermissions({"file:read", "write:aFile.txt"});
    void someMethod();
    最后说一遍, 需要处理可能的AuthorizationException异常
     
    注解方式是在方法级别的控制,无法做类级别的控制访问。
    过滤器方式是根据访问的URL进行控制。允许使用*通配URL,所以可以进行粗粒度,也可以进行细粒度控制。
     

    2.4 在JSP页面使用shiro标签

    使用shiro标签, 根据权限过滤部分内容
     
    <shiro:authenticated>      登录之后
    <shiro:notAuthenticated> 没有登录
    <shiro:hasRole name="abc">     拥有角色abc
    <shiro:lacksRole name="abc">   没有角色abc
    <shiro:hasPermission name="abc">    拥有权限资源abc
    <shiro:lacksPermission name="abc">  没有abc权限资源
    <shiro:principal>   取回签名对象
  • 相关阅读:
    jq ajax之beforesend(XHR)
    WPF string,color,brush之间的转换
    wpf后台设置颜色(背景色,前景色)
    VMWare之——宿主机与虚拟机互相ping通,宿主机ping通另一台机器的虚拟机
    动态SQL的执行,注:exec sp_executesql 其实可以实现参数查询和输出参数的
    【SQLSERVER】动态游标的实现
    减小Delphi 2010/delphi XE编译出来的文件大小
    正确理解 SqlConnection 的连接池机制[转]
    关于VS2005中C#代码用F12转到定义时,总是显示从元数据的问题
    通过cmd命令安装、卸载、启动和停止Windows Service(InstallUtil.exe)
  • 原文地址:https://www.cnblogs.com/myJavaEE/p/6677865.html
Copyright © 2011-2022 走看看