zoukankan      html  css  js  c++  java
  • shiro快速入门案例

    Apache Shiro是什么?

    • Apache Shiro是一个强大且易用的Java安全框架,可执行身份验证(登录)、授权、密码学和会话管理

    架构图

    组件基本说明:

    • subject(主体):接收客户端账号密码,有一系列的认证授权方法
    • security manager(安全管理器):管理所有的subject,并使用底层组件完成操作
    • authenticator(认证/登录校验):对subject的身份进行认证,最简单可以理解为对用户的账号密码进行校验
    • authorize(授权):subject认证通过后,在访问功能时需要通过授权器判断用户是否有此功能的操作权限
    • realm(域):对当前subject的权限管理数据进行封装(从数据库中获取),分别有认证和授权两个
    • session manager(会话管理器):类似于web session域的session管理域
    • sessionDAO(会话DAO):shiro session的Dao类
    • cache manager(缓存管理器):用于缓存权限信息,提高系统性能
    • crypography(密码学):一套加密api

    快速入门案例

    数据库表:
    user

    user_role

    role_permission

    maven依赖:

    <!-- shiro-core -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.2</version>
    </dependency>
    
    
    <!-- 数据库驱动:mysql -->
    <dependency>
    	<groupId>mysql</groupId>
    	<artifactId>mysql-connector-java</artifactId>
    	<version>5.1.38</version>
    </dependency>
    
    
    <!-- 连接池:druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.6</version>
    </dependency>
    

    ** 数据库工具类:**

    public class DBUtil {
    
    	private DBUtil() {}
    	
    	private static DruidDataSource druidDataSource = null;
    	
    	static {
    		druidDataSource = new DruidDataSource();
    		druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
    		druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
    		druidDataSource.setUsername("root");
    		druidDataSource.setPassword("root");
    	}
    	
    	public static DruidPooledConnection getConnection() throws SQLException {
    		return druidDataSource.getConnection();
    	}
    	
    	public static DataSource getDataSource() {
    		return druidDataSource;
    	}
    	
    }
    

    ** 需要认证授权的用户信息(模拟表填提交的数据):**

    public enum Users {
    	ADMIN("admin", "123456"), TEST("test", "123456");
    	
    	private String username;
    	private String password;
    	Users(String username, String password) {
    		this.username = username;
    		this.password = password;
    	}
    	
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    	
    }
    

    ** 入门案例: **

    /**
     * 使用shiro提供的SimpleAccountRealm进行认证(不支持自定义授权)
     */
    public class SimpleAccountRealmTest {
    	
    	//备用。用于存放查询出来的角色名称
    	private static String[] userRoles = new String[5]; 
    	
    	//创建一个shiro提供的简单Realm,不支持自定义授权
    	private static SimpleAccountRealm realm = new SimpleAccountRealm();
    	
    	//初始化realm信息
    	static {
    		
    		try {
    			
    			DruidPooledConnection connection = DBUtil.getConnection();
    			
    			//获取需要认证用户的user信息
    			PreparedStatement userPrepareStatement = connection.prepareStatement("select * from user where username=?"); 
    			userPrepareStatement.setString(1, Users.ADMIN.getUsername());
    			ResultSet userRs = userPrepareStatement.executeQuery();
    			userRs.next(); //username唯一所以只有一个rs
    			
    			//根据用户信息(username)查找出对应的role
    			PreparedStatement rolePrepareStatement = connection.prepareStatement("select * from user_role where username=?");
    			rolePrepareStatement.setString(1, Users.ADMIN.getUsername());
    			ResultSet roleRs = rolePrepareStatement.executeQuery();
    			
    			int i = 0;
    			while(roleRs.next()) { //可能有多个角色
    				userRoles[i++] = roleRs.getString("role_name");
    			}
    			
    			
    			/**
    			 * 注意:这里的account信息应该是数据库中的信息
    			 */
    			realm.addAccount(userRs.getString("username"), userRs.getString("password"), userRoles); //将该账号信息设置到realm中
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    	}
    	
    	public static void main(String[] args) {
    	
    		// 1. 获取默认的SecurityManager
    		DefaultSecurityManager sm = new DefaultSecurityManager();
    		sm.setRealm(realm);
    		
    		// 2. 设置到工具中
    		SecurityUtils.setSecurityManager(sm);
    		
    		// 3. 获取主体
    		Subject subject = SecurityUtils.getSubject();
    		
    		// 4. 创建token
    		UsernamePasswordToken token = new UsernamePasswordToken(Users.ADMIN.getUsername(), Users.ADMIN.getPassword());
    		
    		// 5. 认证
    		subject.login(token);
    		
    		System.out.println( "是否认证成功: " + subject.isAuthenticated() );
    		System.out.println( "是否有super这个角色: " +  subject.hasRole("super"));
    		System.out.println( "是否有default这个角色: " +  subject.hasRole("default"));
    //		boolean[] hasRoles = subject.hasRoles(Arrays.asList(userRoles)); //是否同时有super和default这个角色
    		
    		
    	}
    
    }
    
    

    shiro提供的realm基本使用

    ** IniRealm: **
    auth.ini:

    [users]
    admin=123456,super,default
    test=123456,default
    
    [roles]
    super=user:delete,user:select,user:update,user:insert
    default=user:select
    

    code:

    /**
     * 使用shiro提供的IniRealm进行认证(使用配置文件保存认证授权信息)
     */
    public class IniRealmTest {
    	
    	private static IniRealm iniRealm;
    	
    	static {
    		iniRealm = new IniRealm("classpath:auth.ini");
    	}
    
    	public static void main(String[] args) {
    
            
    
            // 1. 获取默认的SecurityManager
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(iniRealm);
    
            // 2. 设置到工具中
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            
            // 3. 获取主体
            Subject subject = SecurityUtils.getSubject();
    
            // 4. 创建token
            UsernamePasswordToken token = new UsernamePasswordToken(Users.ADMIN.getUsername(), Users.ADMIN.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), Users.TEST.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken("AAAA", "XXX"); //UnknownAccountException 没有该账号
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), "XXX"); //IncorrectCredentialsException 凭证错误(密码错误)
            
            // 5. 认证
            subject.login(token);
    
    		System.out.println( "是否认证成功: " + subject.isAuthenticated() );
    		System.out.println( "是否有super这个角色: " +  subject.hasRole("super") );
    		System.out.println( "是否有default这个角色: " +  subject.hasRole("default") );
    		
    		// 6. 授权
    		System.out.println( "是否有user:select权限 " + subject.isPermitted("user:select"));
    		System.out.println( "是否有user:delete权限 " + subject.isPermitted("user:delete"));
    		System.out.println( "是否有user:update权限 " + subject.isPermitted("user:update"));
    		System.out.println( "是否有user:insert权限 " + subject.isPermitted("user:insert"));
    
    		
    	}
    
    }
    

    ** JdbcRealm: **

    /**
     * 使用shiro提供的JdbcRealm进行认证(使用数据库数据)
     */
    public class JdbcRealmTest {
    
    	private static JdbcRealm jdbcRealm;
    	
    	static {
    		jdbcRealm = new JdbcRealm();
            jdbcRealm.setDataSource(DBUtil.getDataSource());
            jdbcRealm.setPermissionsLookupEnabled(true);	// 使用JdbcRealm时要设置权限开关,默认为false
            
            // 自定义SQL语句(如果不设置自定义的SQL语句则按照JdbcRealm内置的模板SQL语句进行数据库操作,可以进入JdbcRealm查看)
            String sql = "select password from user where username = ?";
            jdbcRealm.setAuthenticationQuery(sql);
    
            String roleSql = "select role_name from user_role where username = ?";
            jdbcRealm.setUserRolesQuery(roleSql);
            
            String permissionSql = "select permission from role_permission where role_name = ?";
            jdbcRealm.setPermissionsQuery(permissionSql);
    	}
    	
    	public static void main(String[] args) {
    
            // 1. 获取默认的SecurityManager
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(jdbcRealm);
    
            // 2. 设置到工具中
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            
            // 3. 获取主体
            Subject subject = SecurityUtils.getSubject();
    
            // 4. 创建token
            UsernamePasswordToken token = new UsernamePasswordToken(Users.ADMIN.getUsername(), Users.ADMIN.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), Users.TEST.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken("AAAA", "XXX"); //UnknownAccountException 没有改账号
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), "XXX"); //IncorrectCredentialsException 凭证错误(密码错误)
            
            // 5. 认证
            subject.login(token);
    
    		System.out.println( "是否认证成功: " + subject.isAuthenticated() );
    		System.out.println( "是否有super这个角色: " +  subject.hasRole("super") );
    		System.out.println( "是否有default这个角色: " +  subject.hasRole("default") );
    		
    		// 6. 授权
    		System.out.println( "是否有user:select权限 " + subject.isPermitted("user:select"));
    		System.out.println( "是否有user:delete权限 " + subject.isPermitted("user:delete"));
    		System.out.println( "是否有user:update权限 " + subject.isPermitted("user:update"));
    		System.out.println( "是否有user:insert权限 " + subject.isPermitted("user:insert"));
    		
    	}
    
    }
    

    自定义Realm(参考JdbcRealm)

    ** 辅助类: **

    /**
     * MyRealm的辅助类(可以定义成内部类)
     */
    public class UserDaoUtil {
    	
    	private UserDaoUtil(){ }
    	
    	private static Connection conn;
    
    	static {
    		try {
    			conn = DBUtil.getConnection();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    	/**
    	 * 根据username获取SimpleAccount
    	 * @param username
    	 * @param realmName
    	 * @return
    	 */
    	public static SimpleAccount getSimpleAccount(String username, String realmName) {
    		
    		PreparedStatement prepareStatement = null;
    		ResultSet rs = null;
    		SimpleAccount account = null;
    		try {
    			
    			prepareStatement = conn.prepareStatement("select * from user where username = ?");
    			prepareStatement.setString(1, username);
    			rs = prepareStatement.executeQuery();
    			rs.next();
    			
    			account = new SimpleAccount(rs.getString("username"), rs.getString("password"), realmName);
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		return account;
    	}
    	
    	
    	/**
    	 * 根据username获取role
    	 * @param username
    	 * @return
    	 */
    	public static Set<String> getRoleNamesForUser(String username) {
    
    		PreparedStatement prepareStatement = null;
    		ResultSet rs = null;
    		Set<String> roles = null;
    		try {
    			roles = new HashSet<>();
    			prepareStatement = conn.prepareStatement("select * from user_role where username = ?");
    			prepareStatement.setString(1, username);
    			rs = prepareStatement.executeQuery();
    			
    			while(rs.next()) {
    				roles.add( rs.getString("role_name") );
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		return roles;
    	}
    	
    	/**
    	 * 获取Permissions
    	 * @param username
    	 * @param roleNames
    	 * @return
    	 */
    	public static Set<String> getPermissions(Set<String> roleNames) {
    		
    		PreparedStatement prepareStatement = null;
    		ResultSet rs = null;
    		Set<String> permissions = null;
    		try {
    			
    			permissions = new HashSet<>();
    			
    			for (String roleName : roleNames) {
    				
    				prepareStatement = conn.prepareStatement("select * from role_permission where role_name = ?");
    				prepareStatement.setString(1, roleName);
    				rs = prepareStatement.executeQuery();
    				
    				while(rs.next()) {
    					permissions.add(rs.getString("permission"));
    				}
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		return permissions;
    	}
    	
    }
    

    ** 自定义Realm: **

    public class MyRealmTest {
    
    	private static MyRealm myRealm;
    	
    	static {
    		myRealm = new MyRealm();
    	}	
    	
    	public static void main(String[] args) {
    		
            // 1. 获取默认的SecurityManager
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(myRealm);
    
            // 2. 设置到工具中
            SecurityUtils.setSecurityManager(defaultSecurityManager);
            
            // 3. 获取主体
            Subject subject = SecurityUtils.getSubject();
    
            // 4. 创建token
            UsernamePasswordToken token = new UsernamePasswordToken(Users.ADMIN.getUsername(), Users.ADMIN.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), Users.TEST.getPassword());
    //        UsernamePasswordToken token = new UsernamePasswordToken("AAAA", "XXX"); //UnknownAccountException 没有改账号
    //        UsernamePasswordToken token = new UsernamePasswordToken(Users.TEST.getUsername(), "XXX"); //IncorrectCredentialsException 凭证错误(密码错误)
            
            // 5. 认证
            subject.login(token);
    		System.out.println( "是否认证成功: " + subject.isAuthenticated() );
    		
    		System.out.println("----------------------------------------------------------------");
    		
    		System.out.println( "是否有super这个角色: " +  subject.hasRole("super") );
    		System.out.println( "是否有default这个角色: " +  subject.hasRole("default") );
    		
    		System.out.println("----------------------------------------------------------------");
    		
    		// 6. 授权
    		System.out.println( "是否有user:select权限 " + subject.isPermitted("user:select"));
    		System.out.println( "是否有user:delete权限 " + subject.isPermitted("user:delete"));
    		System.out.println( "是否有user:update权限 " + subject.isPermitted("user:update"));
    		System.out.println( "是否有user:insert权限 " + subject.isPermitted("user:insert"));
    	}
    
    }
    
  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9671761.html
Copyright © 2011-2022 走看看