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"));
    	}
    
    }
    
  • 相关阅读:
    Codeforces Round #420 (Div. 2) A-E
    Codeforces Round #419 (Div. 2) A-E
    Bzoj4423 [AMPPZ2013]Bytehattan
    51nod1471 小S的兴趣
    Bzoj2629 binomial
    51nod1056 最长等差数列 V2
    51nod1055 最长等差数列
    51nod1110 距离之和最小 V3
    20. 有效的括号
    155.最小栈
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9671761.html
Copyright © 2011-2022 走看看