1. 程式人生 > >Apache Shiro 許可權控制 使用自定義的JdbcRealm(3)

Apache Shiro 許可權控制 使用自定義的JdbcRealm(3)

使用自定義的realm 時需要配置shiro.ini 檔案 以及建一個類  MyJdbcRealm  繼承自  AuthorizingRealm 重寫其中的兩個方法

        /**
	 * 登入驗證
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
               return null;
        }
        /**
	 * 為當前登入的使用者授予角色和許可權
	 */ 
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
            return null;
        }

在shiro中配置

[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp
myRealm=com.taisen.realm.MyJdbcRealm
securityManager.realms=$myRealm


[urls]
/login=anon
/admin=authc
/student=roles[teacher]

/teacher=perms["teacher:query","teacher:add"]

下面是具體的實現方法:

需要連線資料庫  DBUtil

public class DBUtil {
	
	private static final String username = "root";
	private static final String password = "root";
	private static final String className = "com.mysql.jdbc.Driver";
	private static final String url = "jdbc:mysql://localhost:3306/db_shiro?useUnicode=true&characterEncoding=utf8&useSSL=false";
	
	public static Connection conn = null;
	public static PreparedStatement pstmt = null;
	
	public static Connection getConnection() throws Exception{
		Class.forName(className);
		conn = DriverManager.getConnection(url, username, password);
		return conn;
	}
	
	public static void close(Connection conn,PreparedStatement pstmt,ResultSet rs) throws SQLException{
		conn.close();
		pstmt.close();
		if(rs != null){
			rs.close();
		}
	}
	
	public static void close(Connection conn,PreparedStatement pstmt) throws SQLException{
		close(conn,pstmt,null);
	}
	
	public static void main(String[] args) {
		try {
			Connection conn = getConnection();
			if(conn != null){
				System.out.println("資料庫連線成功!");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

操作資料庫UserDao:

public class UserDao {
	
	private Connection connection;
	
	public UserDao() throws Exception {
		// TODO Auto-generated constructor stub
		connection = DBUtil.getConnection();
	}
	
	public User getByUserName(String userName) throws Exception{
		User resultUser = null;
		
		String sql = "select * from t_user where userName = ?";
		PreparedStatement pstmt = connection.prepareStatement(sql);
		pstmt.setString(1, userName);
		ResultSet rs = pstmt.executeQuery();
		if(rs.next()){
			resultUser = new User();
			resultUser.setId(rs.getInt("id"));
			resultUser.setUserName(rs.getString("userName"));
			resultUser.setPassword(rs.getString("password"));
		}
		DBUtil.close(connection, pstmt,rs);
		return resultUser;
	}
	
	/*public static void main(String[] args) throws Exception {
		UserDao userDao = new UserDao();
		User user = userDao.getByUserName("java");
		System.out.println(user);
	}*/
	
	
	/**
	 * 根據userName 獲取到roles
	 * @param userName
	 * @return
	 * @throws SQLException 
	 */
	public Set<String> getRoles(String userName) throws SQLException {
		Set roles = new HashSet();
		String sql = "select * from t_role r LEFT JOIN t_user u on r.id = u.role_id where u.userName = ?";
		PreparedStatement pstmt = connection.prepareStatement(sql);
		pstmt.setString(1, userName);
		ResultSet rs = pstmt.executeQuery();
		if(rs.next()){
			roles.add(rs.getString("roleName"));
		}
		return roles;
	}
	
	/**
	 * 根據傳入的userName 返回得到的perms
	 * @param object
	 * @return
	 * @throws SQLException 
	 */
	public Set<String> getPerms(String userName) throws SQLException {
		Set permissions = new HashSet();
		String sql = "select * from t_user u,t_role r,t_permission p where u.role_id = r.id and p.role_id = r.id and u.userName = ?";
		PreparedStatement pstmt = connection.prepareStatement(sql);
		pstmt.setString(1, userName);
		ResultSet rs = pstmt.executeQuery();
		if(rs.next()){
			permissions.add(rs.getString("permissionName"));
		}
		DBUtil.close(connection, pstmt, rs);
		return permissions;
	}

}

重點 MyJdbcRealm。  在點選登入按鈕後後到Controller中的login方法  呼叫subject.login(token)方法時會呼叫下面的自定義

Realm

public class MyJdbcRealm extends AuthorizingRealm{
	
	/**
	 * 登入驗證
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		AuthenticationInfo auth = null;
		try {
			UserDao userdao = new UserDao();
			String username = (String) token.getPrincipal(); //獲取到userName
			User user = userdao.getByUserName(username);
			if(user != null){
				auth = new SimpleAuthenticationInfo(username, user.getPassword(),"XX");
				return auth;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return auth;
		}
		return auth;
	}
	
	
	/**
	 * 為當前登入的使用者授予角色和許可權
	 */ 
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		String userName = (String)principals.getPrimaryPrincipal();
		UserDao userdao;
		SimpleAuthorizationInfo auth = null;
		try {
			userdao = new UserDao();
			auth = new SimpleAuthorizationInfo();
			auth.setRoles(userdao.getRoles(userName));
			auth.setStringPermissions(userdao.getPerms(userName));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return auth;
	}
	

}
每次發起請求時都會驗證許可權。