1. 程式人生 > >Shiro (筆記) InI 配置

Shiro (筆記) InI 配置

https://www.w3cschool.cn/shiro/h5it1if8.html

即使沒接觸過 IoC 容器的知識,如上配置也是很容易理解的:

  1. 物件名 = 全限定類名 相對於呼叫 public 無參構造器建立物件
  2. 物件名. 屬性名 = 值 相當於呼叫 setter 方法設定常量值
  3. 物件名. 屬性名 =$ 物件引用 相當於呼叫 setter 方法設定物件引用
package com.dudu.course2;

import java.nio.file.attribute.UserPrincipalLookupService;
import java.util.Arrays;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.authz.permission.WildcardPermissionResolver;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Assert;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * AtLeastOneSuccessfulStrategy 只要有一個Realm驗證成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份驗證成功的認證資訊;
 * AllSuccessfulStrategy 所有Realm驗證成功才算成功,且返回所有Realm身份驗證成功的認證資訊,如果有一個失敗就失敗了。
 * ModularRealmAuthenticator預設使用AtLeastOneSuccessfulStrategy策略。
 * FirstSuccessfulStrategy 只要有一個Realm驗證成功即可,只返回第一個Realm身份驗證成功的認證資訊,其他的忽略;
 * @author xl
 *
 */
public class ShiroTest2INI {

	public void test(){
		DefaultSecurityManager securityManager = new DefaultSecurityManager();
		//設定authenticator 驗證賬戶賬號
		ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
		authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
		securityManager.setAuthenticator(authenticator);
		
		//設定authorizer 授權
		ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
		authorizer.setPermissionResolver(new WildcardPermissionResolver());
		securityManager.setAuthorizer(authorizer);
		
		//設定realm
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost:3306/shiro");
		dataSource.setUsername("root");
		dataSource.setPassword("123456");
		
		JdbcRealm jdbcRealm = new JdbcRealm(); 
		jdbcRealm.setDataSource(dataSource);
		jdbcRealm.setPermissionsLookupEnabled(true);
		securityManager.setRealms(Arrays.asList((Realm) jdbcRealm));
		
		SecurityUtils.setSecurityManager(securityManager);
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken();
		subject.login(token);
		Assert.assertTrue(subject.isAuthenticated());
		
	}
}

2、等價的 INI 配置(shiro-config.ini)

[main]
\#authenticator
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
authenticator.authenticationStrategy=$authenticationStrategy
securityManager.authenticator=$authenticator
\#authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer
\#realm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
\#dataSource.password=
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
jdbcRealm.permissionsLookupEnabled=true
securityManager.realms=$jdbcRealm
[main]
\#提供了對根物件securityManager及其依賴的配置
securityManager=org.apache.shiro.mgt.DefaultSecurityManager
…………
securityManager.realms=$jdbcRealm
[users]
\#提供了對使用者/密碼及其角色的配置,使用者名稱=密碼,角色1,角色2
username=password,role1,role2
[roles]
\#提供了角色及許可權之間關係的配置,角色=許可權1,許可權2
role1=permission1,permission2
[urls]
\#用於web,提供了對web url攔截相關的配置,url=攔截器[引數],攔截器
/index.html = anon
/admin/** = authc, roles[admin], perms["permission1"]
String str = "hello";
String salt = "123";
String md5 = new Md5Hash(str, salt).toString();//還可以轉換為 toBase64()/toHex() 

如上程式碼通過鹽 “123”MD5 雜湊 “hello”。另外雜湊時還可以指定雜湊次數,如 2 次表示:md5(md5(str)):“new Md5Hash(str, salt, 2).toString()”。

String str = "hello";
String salt = "123";
String sha1 = new Sha256Hash(str, salt).toString(); 

使用 SHA256 演算法生成相應的雜湊資料,另外還有如 SHA1、SHA512 演算法。

Shiro 還提供了通用的雜湊支援:

String str = "hello";
String salt = "123";
//內部使用MessageDigest
String simpleHash = new SimpleHash("SHA-1", str, salt).toString();   

通過呼叫 SimpleHash 時指定雜湊演算法,其內部使用了 Java 的 MessageDigest 實現。

為了方便使用,Shiro 提供了 HashService,預設提供了 DefaultHashService 實現。

DefaultHashService hashService = new DefaultHashService(); //預設演算法SHA-512
hashService.setHashAlgorithmName("SHA-512");
hashService.setPrivateSalt(new SimpleByteSource("123")); //私鹽,預設無
hashService.setGeneratePublicSalt(true);//是否生成公鹽,預設false
hashService.setRandomNumberGenerator(new SecureRandomNumberGenerator());//用於生成公鹽。預設就這個
hashService.setHashIterations(1); //生成Hash值的迭代次數
HashRequest request = new HashRequest.Builder()
            .setAlgorithmName("MD5").setSource(ByteSource.Util.bytes("hello"))
            .setSalt(ByteSource.Util.bytes("123")).setIterations(2).build();
String hex = hashService.computeHash(request).toHex(); 
  1. 首先建立一個 DefaultHashService,預設使用 SHA-512 演算法;
  2. 以通過 hashAlgorithmName 屬性修改演算法;
  3. 可以通過 privateSalt 設定一個私鹽,其在雜湊時自動與使用者傳入的公鹽混合產生一個新鹽;
  4. 可以通過 generatePublicSalt 屬性在使用者沒有傳入公鹽的情況下是否生成公鹽;
  5. 可以設定 randomNumberGenerator 用於生成公鹽;
  6. 可以設定 hashIterations 屬性來修改預設加密迭代次數;
  7. 需要構建一個 HashRequest,傳入演算法、資料、公鹽、迭代次數。

SecureRandomNumberGenerator 用於生成一個隨機數:

SecureRandomNumberGenerator randomNumberGenerator =
     new SecureRandomNumberGenerator();
randomNumberGenerator.setSeed("123".getBytes());
String hex = randomNumberGenerator.nextBytes().toHex();