如何快速的入門shiro(三)自定義一個Realm

當shiro內置的IniRealm和JdbcRealm都不滿足我們的要求時,怎麼辦呢?別擔心,shiro還爲我們考慮到了這個情況,我們可以繼承AuthorizingRealm,然後重寫doGetAuthorizationInfo和doGetAuthenticationInfo這兩個方法就可以了。doGetAuthorizationInfo方法重寫我們需要授權的代碼,doGetAuthenticationInfo方法重寫我們需要認證的代碼,廢話不多說,直接上圖和代碼。

1. 在博客一的基礎上,shiroTest.java同路徑文件夾下新建一個CutomRealm.java文件

代碼如下

public class CustomRealm extends AuthorizingRealm {

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub

		return null;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub

        return null;
	}

}

表示CustomRealm繼承了AuthorizingRealm類,並且需要覆蓋重寫doGetAuthorizationInfo和doGetAuthenticationInfo這兩個方法

2. 重寫doGetAuthenticationInfo方法表示我們需要進行認證的過程

代碼如下

	// 模擬數據庫存放用戶名和密碼
	Map<String,String> userMap=new HashMap<String,String>();
	{
		userMap.put("zhangsan", "123");
		userMap.put("lisiplus", "456");
		super.setName("CustomerRealm");
	}

    @Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub

		// 從subject客體中取得當前用戶名
		String userName=(String)token.getPrincipal();
		// 模擬從數據庫取得當前用戶名對應的密碼
		String password=getPasswordByUsername(userName);
		if(password==null)
		{
			return null;
		}
		// 取的當前認證的信息 
		SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(userName,password,"CustomerRealm");
		return simpleAuthenticationInfo;
		
	}

	private String getPasswordByUsername(String userName) {
		// TODO Auto-generated method stub
		return userMap.get(userName);
	}

3. 新建一個用於測試CustomRealmTest.java文件

代碼如下

public class CustomRealmTest {
	
	@Test
	public void Test() {

		CustomerRealm customerRealm=new CustomerRealm();
		DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
		defaultSecurityManager.setRealm(customerRealm);
		SecurityUtils.setSecurityManager(defaultSecurityManager);
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
		subject.login(token);
		System.out.println(subject.getPrincipal() + "是否驗證成功" + subject.isAuthenticated());

      }
}

編譯運行可得如圖,表示shiro使用了我們自定義的Realm

4. 重寫doGetAuthorizationInfo方法表示我們需要授權的過程

代碼如下

    // 模擬數據庫存放的角色名
	Map<String,String> roles=new HashMap<String,String>();
	{
		roles.put("zhangsan","admin");
		roles.put("lilsiplus","adminpro");
	}
	
	// 模擬數據庫存放的權限名
	Map<String,String> permissions=new HashMap<String,String>();
	{
		permissions.put("admin", "update");
		permissions.put("admin","delete");
		permissions.put("adminpro","update");
		permissions.put("adminpro", "add");
	}
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		
		String userName=(String)principals.getPrimaryPrincipal();
		Set<String> roles=getRolesByUsername(userName);
		Set<String> permissions=getPermissionsByUserName(userName);
		
		SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.setRoles(roles);
		simpleAuthorizationInfo.setStringPermissions(permissions);
		return simpleAuthorizationInfo;
	}

	private Set<String> getPermissionsByUserName(String userName) {
		// TODO Auto-generated method stub
		Set<String> permissions=new HashSet<String>();
		permissions.add("delete");
		permissions.add("update");
		return permissions;
	}

	private Set<String> getRolesByUsername(String userName) {
		// TODO Auto-generated method stub
		Set<String> roles=new HashSet<String>();
		roles.add("admin");
		roles.add("test");
		return roles;
	}

5. 在CustomRealmTest.java文件加入測試授權的代碼

代碼如下

        // 使用ArrayList存儲角色
		List<String> roles = new ArrayList<String>();
		roles.add("admin");
		roles.add("adminplus");
		roles.add("adminpro");
		// 循環測試角色
		for (String role : roles) {
			System.out.println("當前用戶是" + subject.getPrincipal() + "\t 是否具有" + role + "角色 \t" + subject.hasRole(role));
		}

		// 使用arraylist存放權限組
		List<String> permissions = new ArrayList<String>();
		permissions.add("update");
		permissions.add("delete");
		permissions.add("add");
		permissions.add("get");
		// 循環驗證當前用戶是否具有對應的權限
		for (String permission : permissions) {
			System.out.println("當前用戶是" + subject.getPrincipal() + "\t 是否具有" + permission + "權限 \t"
					+ subject.isPermitted(permission));
		}
		
		System.out.println(subject.isPermitted("get"));

		// 登出當前用戶
		subject.logout();
		// 驗證當前用戶是否登出
		System.out.println(subject.getPrincipal() + "是否登錄成功?" + subject.isAuthenticated());

編譯運行效果如圖,表示shiro也採用了我們自定義Realm的授權過程

6. 總結

6.1 由於自定義Realm的過程還是很簡單,幾乎也沒有踩坑的過程

6.2 自定義Realm需要繼承AuthorizingRealm類

6.3 需要在doGetAuthorizationInfo這個方法內重寫我們授權的代碼

6.4 需要在doGetAuthenticationInfo這個方法內重寫我們認證的代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章