shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。

shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。

使用shiro实现系统 的权限管理,有效提高开发效率,从而降低开发成本。

一.先上例子

1.配置pom.xml加jar包

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架_02

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.4</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

maven依赖

2.ini配置文件

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架_02

#用户信息配置
[users]
admin=123,role1
#自定义配置secrityManage的相关依赖
[main]
realmDemo=com.hc360.shiro.realm.RealmDemo
securityManager.realms=$realmDemo
#角色
[roles]  
role1=user:create,user:update
role2=user:create,user:delete

ini配置文件

3.自定义realms(可以不加,realms有两个方法:一个是认证:判断用户名和密码是否正确、一个是授权:从数据库里查出权限,判断是否拥有权限)

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架_02

package com.hc360.shiro.realm;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class RealmDemo extends AuthorizingRealm{

    /**
     * 认证,登陆时调用
     * 
     * @author liuzunli
     * @date 2016-4-20
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        System.out.println(username);
        //判断用户名是否正确
        if(!"admin".equals(username)){
            throw new UnknownAccountException();//或者return null;
        }
        String password = "123";
        return new SimpleAuthenticationInfo(username,password,this.getName());
    }
    
    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
     * 
     * @author liuzunli
     * @date 2016-4-20
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        
        //认证设置的第一个参数
        String username = (String) principals.getPrimaryPrincipal();
        
        //返回的权限信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        
        //通过用户名查询用户的角色
        Set<String> roleList = new HashSet<String>();
        roleList.add("role1");
        
        simpleAuthorizationInfo.setRoles(roleList);
        
        
        //通过用户名查询数据库、查出用户拥有的权限-----
        List<String> permissionList = new ArrayList<String>();
        permissionList.add("user:create");
        permissionList.add("user:delete");
        permissionList.add("user:update");
        
        simpleAuthorizationInfo.addStringPermissions(permissionList);
        return simpleAuthorizationInfo;
    }

}

realms

4.测试

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架_02

package com.hc360.shiro;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * shiro测试
 * 
 * @author liuzunli
 * @date 2016-4-20
 */
public class ShiroTest {
    
    /**
     * 登录/退出
     * 
     * @author liuzunli
     * @date 2016-4-20
     */
    @Test
    public void testLogin() {
         //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
        Factory<SecurityManager> factory =  new IniSecurityManagerFactory("resources\\shiro.ini");
        //2、得到SecurityManager实例 并绑定给SecurityUtils
        SecurityManager securityManager = factory.getInstance();  
        SecurityUtils.setSecurityManager(securityManager);  
        //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)  
        Subject subject = SecurityUtils.getSubject();  
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");  
      
        try {  
            //4、登录,即身份验证  
            subject.login(token);  
        } catch (AuthenticationException e) {  
            //5、身份验证失败  
            e.printStackTrace();
        }  
        System.out.println("是否认证通过:"+subject.isAuthenticated());
        
        System.out.println("是否拥有角色:"+subject.hasRole("role1"));
        
        System.out.println("是否拥有权限:"+subject.isPermitted("user:create"));
        
        
        //6、退出  
        subject.logout();  
        System.out.println("退出后是否认证通过:"+subject.isAuthenticated());
    }
    
    

}

登录、权限等判断

上边就是一个完整的shiro例子

二.shiro架构

Java shiro 权限框架 shiro框架怎么实现权限控制_System_09

 

 subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

 

securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。

 

authenticator:认证器,主体进行认证最终通过authenticator进行的。

 

authorizer:授权器,主体进行授权最终通过authorizer进行的。

 

sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。

SessionDao:  通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。

 

cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。

 

realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。

 

注意:在realm中存储授权和认证的逻辑。

 

cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。

比如 md5散列算法。

三.下面再看例子

1.配置文件ini解释

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架

Java shiro 权限框架 shiro框架怎么实现权限控制_Java shiro 权限框架_02

[main]  
#提供了对根对象securityManager及其依赖的配置  
securityManager=org.apache.shiro.mgt.DefaultSecurityManager  
…………  
securityManager.realms=$jdbcRealm  
  
[users]  
#提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2  
username=password,role1,role2  
  
[roles]  
#提供了角色及权限之间关系的配置,角色=权限1,权限2  
role1=permission1,permission2  
  
[urls]  
#用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器  
/index.html = anon  
/admin/** = authc, roles[admin], perms["permission1"]

ini配置文件解释

2.shiro流程

  • 1、通过ini配置文件创建securityManager
  • 2、调用subject.login方法主体提交认证,提交的token
  • 3、securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。
  • 4、ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息
  • 5、IniRealm根据输入的token(UsernamePasswordToken)从 shiro-first.ini查询用户信息,根据账号查询用户信息(账号和密码)
  •          如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)
  •          如果查询不到,就给ModularRealmAuthenticator返回null
  • 6、ModularRealmAuthenticator接收IniRealm返回Authentication认证信息
  • org.apache.shiro.authc.UnknownAccountException)
  • org.apache.shiro.authc.IncorrectCredentialsException)

3.自定义realms

  1.什么情况下用realms:大多数情况下都要用realms,因为大多数情况下,用户认证、用户权限等都是从数据库里取出来的,因此ini配置文件实际上大多数情况下没有,因为里边的数据都是从数据库里查出来的。

  2.realms里有2个方法:doGetAuthenticationInfo:认证,一般情况下form表单提交过来的数据,然后通过这个方法连接数据库查询用户信息,判断用户名和密码是否正确。返回AuthenticationInfo对象,里边会包含用户、密码、盐等信息

   doGetAuthorizationInfo:授权,认证方法返回的用户信息,然后查询数据库,把此用户的权限和角色取出来,放在放回的对象AuthorizationInfo里

4.测试

//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
		Factory<SecurityManager> factory =  new IniSecurityManagerFactory("resources\\shiro.ini");
		//2、得到SecurityManager实例 并绑定给SecurityUtils
		SecurityManager securityManager = factory.getInstance();  
	    SecurityUtils.setSecurityManager(securityManager);  
	    //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)  
	    Subject subject = SecurityUtils.getSubject();  
	    UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");  

	    try {  
	        //4、登录,即身份验证  
	        subject.login(token);  
	    } catch (AuthenticationException e) {  
	        //5、身份验证失败  
	    	e.printStackTrace();
	    }  
	    System.out.println("是否认证通过:"+subject.isAuthenticated());

	    System.out.println("是否拥有角色:"+subject.hasRole("role1"));

	    System.out.println("是否拥有权限:"+subject.isPermitted("user:create"));

	    //6、退出  
	    subject.logout();  
	    System.out.println("退出后是否认证通过:"+subject.isAuthenticated());