Shiro安全框架

Shiro

搭建

  • pom.xml: 导入库

    <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
            <!--缓存包-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-ehcache</artifactId>
                <version>1.4.0</version>
            </dependency>
            <!--核心包-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.4.0</version>
            </dependency>
    
  • web.xml: 过滤器

     <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>
    
  • xml: bean设置

    1. anno,任何人都可以访问;
    2. authc:必须是登录之后才能进行访问,不包括remember me;
    3. user:登录用户才可以访问,包含remember me;
    4. perms:指定过滤规则,这个一般是扩展使用,不会使用原生的
    
    	<?xml version="1.0" encoding="UTF-8"?>
    <beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 授权 认证 -->
        <bean id="jdbcRealm"  class="controller.UserRealm"></bean>
        <!-- Shiro安全管理器 -->
        <bean id="securityManager"  class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm"  ref="jdbcRealm"></property>
        </bean>
        	//id必须与过滤器名称一致
        <bean id="shiroFilter"  class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager"  ref="securityManager"></property>
            <property name="loginUrl"  value="/login.html"></property>
            <property name="successUrl"  value="/index"></property>
            <!-- 用户访问未对其授权的资源时,所显示的连接 -->
            <property name="unauthorizedUrl"  value="/unauthorizedUrl"></property>
           
            <property name="filterChainDefinitions">
                <value>
                    /inlogin=anon
                    /test/**=roles[role1]
                    /index=authc
                </value>
            </property>
        </bean>
    </beans>
    
  • Realm实现

    		package controller;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.apache.shiro.SecurityUtils;
    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.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    @Component
    public class UserRealm extends AuthorizingRealm
    {
        protected Logger logger =  LoggerFactory.getLogger(this.getClass());  
        @Override
        protected AuthorizationInfo  doGetAuthorizationInfo(PrincipalCollection arg0)
        {
            UsernamePasswordToken token =  (UsernamePasswordToken)  SecurityUtils.getSubject().getPrincipal();
            String username = token.getUsername();
            logger.info(username + "授权...");
            // 从数据库中查找该用户的角色和权限
            SimpleAuthorizationInfo sainfo = new  SimpleAuthorizationInfo();
            Set<String> roles = new  HashSet<String>();
            roles.add("admin");
            //roles.add("role1");
            Set<String> permissions = new  HashSet<String>();
            permissions.add("add");
            permissions.add("delete");
            sainfo.setRoles(roles);
             sainfo.setStringPermissions(permissions);
            return sainfo;
        }
        @Override
        protected AuthenticationInfo  doGetAuthenticationInfo(AuthenticationToken  arg0)
            throws AuthenticationException
        {
        UsernamePasswordToken token =  (UsernamePasswordToken) arg0;
            String username = token.getUsername();
            // 根据username从数据库查找用户,得到密码
            // 假设找到的用户如下
            // User user =  userService.findByUsername(username)
    //        if (null == user)
    //        {
    //            throw new  AccountException("username is not exist");
    //        }
    //        else if  (!user.getPassword().equals(new  String(token.getPassword())))
    //        {
    //            throw new  AccountException("password is not right");
    //        }
    //        else
    //        {
                // 登陆成功
                logger.info("{} login success.",  username);
    //        }
            return new  SimpleAuthenticationInfo(arg0,  "21232f297a57a5a743894a0e4a801fc3", username);
        }
    }
    

登录验证

  • 验证
	Subject sub = SecurityUtils.getSubject();
	UsernamePasswordToken token = new UsernamePasswordToken(username,password);
	 sub.login(token);    
  • 退出登录sub.logout();
  • 获取session:sub.getsession();

权限检验

  • xml属性

    	 <property name="filterChainDefinitions">
    	            <value>
    	                /callback=anon
    	                /=authc
    	                /**=anon
    	            </value>
    	        </property>
    
  • annotation

    1. @RequiresAuthentication
      验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。

    2. @RequiresUser
      验证用户是否被记忆,user有两种含义

      • 一种是成功登录的(subject.isAuthenticated() 结果为true);
      • 另外一种是被记忆的(subject.isRemembered()结果为true)。
    3. @RequiresGuest
      验证是否是一个guest的请求,与@RequiresUser完全相反。
      换言之,RequiresUser == !RequiresGuest。
      此时subject.getPrincipal() 结果为null.

    4. @RequiresRoles

      	@RequiresRoles("aRoleName");
      	 						 void someMethod();
      

      如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException。

    5. @RequiresPermissions

      	@RequiresPermissions({"file:read", "write:aFile.txt"} )   void
      		someMethod();
      

      要求subject中必须同时含有file:read和write:aFile.txt的权限才能执行方法someMethod()

  • tag标签

    1. <shiro:guest>
      	游客访问 <a href = "login.jsp"></a> 
      </shiro:guest>  
      
    2. user 标签:用户已经通过认证\记住我 登录后显示响应的内容

      <shiro:user>
      	欢迎[<shiro:principal/>];
      	登录 <a href = "logout">;
      	退出</a> 
      </shiro:user> 
      
    3. authenticated标签:用户身份验证通过,即 Subjec.login 登录成功 不是记住我登录的

       <shiro:authenticted>
      	用户[<shiro:principal/>] 
      	已身份验证通过 
      </shiro:authenticted>   
      
    4. notAuthenticated标签:用户未进行身份验证,即没有调用Subject.login进行登录,包括"记住我"也属于未进行身份验证

      <shiro:notAuthenticated>
      	未身份验证(包括"记住我")
      </shiro:notAuthenticated>
      
    5. principal 标签:显示用户身份信息,默认调用

      Subjec.getPrincipal()获取,即Primary Principal
      <shiro:principal property = "username"/>  
      
    6. hasRole标签:如果当前Subject有角色将显示body体内的内容

      <shiro:hashRole name = "admin">
      	用户[<shiro:principal/>] 拥有角色admin
      </shiro:hashRole>
      
    7. hasAnyRoles标签:如果Subject有任意一个角色(或的关系)将显示body体里的内容

      <shiro:hasAnyRoles name = "admin,user">
      	用户[<shiro:pricipal/>]拥有角色admin 或者 user
      </shiro:hasAnyRoles>
      
    8. lacksRole:如果当前 Subjec没有角色将显示body体内的内容

      <shiro:lacksRole name = "admin">
      	用户[<shiro:pricipal/>]没有角色admin 
      </shiro:lacksRole>   
      
    9. hashPermission:如果当前Subject有权限将显示body体内容

      <shiro:hashPermission name ="user:create">
      	用户[<shiro:pricipal/>] 拥有权限user:create 
      </shiro:hashPermission>   
      
    10. lacksPermission:如果当前Subject没有权限将显示body体内容

      <shiro:lacksPermission name = "org:create">
      	用户[<shiro:pricipal/>] 没有权限org:create 
      </shiro:lacksPermission>
      
  • 指定权限

    	Subject currentUser = SecurityUtils.getSubject();
    	    if (currentUser.hasRole("admin")) {
    	        logger.info("-----------啊啊啊啊--admin---------");
    	    }
    	    if (currentUser.hasRole("user")) {
    	        logger.info("-----------user---------");
    	    }
    

注解支持

<!-- 开启shiro的注解支持 -->
	<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
		<!-- 必须改为true,即使用cglib方式为Action创建代理对象。默认值为false,使用JDK创建代理对象,会造成问题 -->
		<property name="proxyTargetClass" value="true"></property>
	</bean>
	
	<!-- 使用shiro框架提供的切面类,用于创建代理对象 -->
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>

无权限时转接

 <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
			<props>
				<prop key="org.apache.shiro.authz.UnauthorizedException">/mg/unauthorized</prop>
			</props>
		</property>
	</bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值