1. 程式人生 > >Shiro應用(一)--- 單獨使用

Shiro應用(一)--- 單獨使用

shiro單獨使用demo:

需要的依賴:

		<!-- 日誌 --> 
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.25</version>
		</dependency>
		<!-- shiro的核心包 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.4.0</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>

shiro-permissions.ini檔案(ini相對於properties檔案的區別在於ini檔案可以分組):

# -----------------------------------------------------------------------------
# 指定使用者名稱以及角色(可選)
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]
hurricane = 123, admin,handsome

# -----------------------------------------------------------------------------
# 指定角色與許可權的對應關係
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = user:add,user:delete
handsome = user:update

簡單的日誌輸出配置log4j.properties:

log4j.rootLogger=info, stdout  
   
log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n 

log4j.logger.com.hurricane = info

主要測試程式碼:

package com.hurricane.learn.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;

public class App {

	public static void main(String[] args) {
		Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permissions.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		
		Subject subject = SecurityUtils.getSubject();
		AuthenticationToken token = new UsernamePasswordToken("hurricane", "123"); 
		try {
			subject.login(token);
		} catch (UnknownAccountException e) {
			System.out.println("使用者名稱不存在");
		} catch (IncorrectCredentialsException e) {
			System.out.println("密碼錯誤");
		} catch (Exception e) {
			System.out.println("未知錯誤");
		}
		
		System.out.println("使用者登入成功:" + subject.isAuthenticated());
		System.out.println("使用者擁有admin角色:" + subject.hasRole("admin"));
		System.out.println("使用者擁有user:delete許可權:" + subject.isPermitted("user:delete"));
		System.out.println("使用者擁有user:query許可權:" + subject.isPermitted("user:query"));
	}
}

以上即可實現shiro最基本的使用。

除此之外,shiro單獨使用通常需要使用自定義的realm進行校驗授權,以及對使用者密碼進行雜湊編碼。

自定義realm:

shiro-permissions.ini中加入:

[main]
customRealm = com.hurricane.learn.shiro.util.CustomRealm
securityManager.realms = $customRealm

CustomRealm的程式碼為:

package com.hurricane.learn.shiro.util;

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

public class CustomRealm extends AuthorizingRealm{

	/**
	 * 授權
	 */
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//primaryPrincipal是認證階段傳入的principal
		Object primaryPrincipal = principals.getPrimaryPrincipal();
		//根據primaryPrincipal從資料庫中查詢對應的角色與許可權,並封裝進要返回的AuthorizationInfo
		info.addRole("role1");
		info.addStringPermission("user:create");
		return info;
	}

	/**
	 * 認證
	 * 返回null代表使用者名稱不存在
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		if (token.getPrincipal()==null || token.getPrincipal().toString().equals("")) {
			return null;
		}
		//判斷使用者名稱是否存在,若不存在,返回null
		// ...
		String dbPassword = "123";
		//將從資料庫中獲取的密碼傳入,shiro會進行校驗,此處傳入的principal應為工程中對使用者資訊進行封裝的類的例項,此處簡寫為一個使用者名稱的字串
		AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),dbPassword,"realm1");
		return info;
	}

}

以上就可以使shiro的校驗走自定義的realm。

對密碼進行加鹽與雜湊:

shiro-permissions.ini中關於自定義域的宣告中指定雜湊的演算法與雜湊的次數:

[main]
credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = md5
credentialsMatcher.hashIterations = 2

customRealm = com.hurricane.learn.shiro.util.CustomRealm
customRealm.credentialsMatcher = $credentialsMatcher

securityManager.realms = $customRealm

在進行認證的方法中傳入鹽與加密後的密碼(一般為從資料庫中讀取的結果),如下:

	/**
	 * 認證
	 * 返回null代表使用者名稱不存在
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		if (token.getPrincipal()==null || token.getPrincipal().toString().equals("")) {
			return null;
		}
		//判斷使用者名稱是否存在,若不存在,返回null
		// ...
		//755ac1a684638060155ccc37625b954b是123加鹽sss並進行2次md5雜湊後的結果
		String dbPassword = "755ac1a684638060155ccc37625b954b";
		//將從資料庫中獲取的密碼傳入,shiro會進行校驗,此處傳入的principal應為工程中對使用者資訊進行封裝的類的例項,此處簡寫為一個使用者名稱的字串
		AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),dbPassword,ByteSource.Util.bytes("sss"),"realm1");
		return info;
	}

參考:

        燕青的視訊教程