shiro學習之配置

shiro學習之配置

1、簡介

    shiro的配置主要分爲兩部分:權限(包括:帳戶、密碼、角色、資源),模塊(包括:認證、受權、session、cache、web)。在學習的過程當中千萬要分開理解,否則很容易混淆。在單獨使用shiro的時候,咱們須要配置xxx.ini文件來修改咱們須要的信息。shiro的每一個部分都是以[xxx]開始,其中[main]是模塊配置,後面的[users],[roles],[urls]則是權限關配置。java

1、權限配置

[users]
#提供了對用戶/密碼及其角色的配置,用戶名=密碼,角色1,角色2
username=password,role1,role2

[roles]
#提供了角色及權限之間關係的配置,角色=權限1,權限2
role1=permission1,permission2

    [users]:下面配置的是帳戶、密碼,以及該帳戶的權限。
mysql

    [roles]:對應每個角色的訪問資源。
web

    (shiro採起的是:一個用戶對應多個角色,一個角色對應多個資源)
redis

2、模塊配置

    a)先看一下 配置 的代碼:這段代碼直接經過源碼實現來一步步new出來的。
sql

//全局sercurityManager
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 ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/shiro");
ds.setUsername("root");
ds.setPassword("");

JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(ds);
jdbcRealm.setPermissionsLookupEnabled(true);
securityManager.setRealms(Arrays.asList((Realm) jdbcRealm));

//將SecurityManager設置到SecurityUtils 方便全局使用
SecurityUtils.setSecurityManager(securityManager);

//登陸
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
subject.login(token);
Assert.assertTrue(subject.isAuthenticated());

    b)介紹:
數據庫

        經過上面這段代碼你們能夠看見幾個主要的實現模塊:SecurityManager、Realm等等。這是經過new的方式來實現的,那咱們平時的配置又有什麼用呢?爲了將這些模塊組裝起來,而且作個一個高可用,低耦合、高擴展性的框架。shiro裏面採用了 IOC 的方式,經過JVM的功能實現的java 反射,來組裝實現低耦合、高可擴展性。在使用者本身開發的擴展中,經過實現shiro提供的接口完成本身的功能,而後經過配置文件替換默認的功能(shiro的源碼很經典,建議你們多讀讀)。
apache

    c)主要模塊實現
緩存

        一、用戶認證: 認證realm、AuthenticationStrategy(這個主要、針對多個realm)session

            認證realm的實現:實現realm接口。這裏每個realm均可以看做是一個元數據查詢接口(能夠是數據庫、txt、redis)。
框架

實現realm:
public class AuthenticationTest implements Realm {
	/**
	 * @see 實現一個認證:每個realm都會和咱們維護的數據聯繫
	 */
	// 認證
	public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("myRealm");
		String userName = (String) token.getPrincipal(); // 帳戶
		String password = new String((char[]) token.getCredentials()); // 密碼
		if (!"userName".equals(userName)) {
			throw new UnknownAccountException();// 帳戶錯誤
		}
		if (!"password".equals(password)) {
			throw new IncorrectCredentialsException();// 密碼錯誤
		}
		return new SimpleAuthenticationInfo(userName, password, getName());
	}

	// 每一個realm都有一個名稱
	public String getName() {
		return "myrealm";
	}

	// 是否支持token
	public boolean supports(AuthenticationToken token) {
		return token instanceof UsernamePasswordToken;
	}

}
配置:ini

##自定義realm全限名####
myRealm1=com.fxl.Test.LearnOne.shiro.authentication.AuthenticationTest
###注入#####
securityManager.realms=$myRealm1

      AuthenticationStrategy的類型:當有多個realm的時候,例若有多個數據元,咱們就須要知道哪個正確才能完成認證,也就是認證策略。官方提供了3種,知足咱們大部分須要。

            FirstSuccessfulStrategy:只要有一個Realm驗證成功便可,只返回第一個Realm身份驗證成功的認證信息,其餘的忽略;

            AtLeastOneSuccessfulStrategy:只要有一個Realm驗證成功便可,和FirstSuccessfulStrategy不一樣,返回全部Realm身份驗證成功的認證信息;(默認)

            AllSuccessfulStrategy:全部Realm驗證成功纔算成功,且返回全部Realm身份驗證成功的認證信息,若是有一個失敗就失敗了。

修改成所用都成功:
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy  
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy

        二、受權:一個subject的權限獲取和每一次訪問的權限驗證,都會使用到authorization模塊。

一、默認實現:
默認的資源字符串:資源標識符:操做:對象實例
eg:
單資源單權限:user:update:5 表示的是:用戶:修改:角色5
單資源多權限:user:update,create:5
單資源全部權限:user:*:5

authorization的realm實現:繼承 authorizingRealm
public class Authoriation extends AuthorizingRealm {
	/***
	 * @see 權限查詢
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
		// 添加角色
		sai.addRole("admim"); // 單角色
		List<String> roles = new ArrayList<String>();// 多角色
		roles.add("admin1");
		roles.add("admin2");
		sai.addRoles(roles);

		// 添加資源權限
		sai.addStringPermission("user:update");
		List<String> permissions = new ArrayList<String>();// 多角色
		permissions.add("user:create");
		permissions.add("user:delete");
		sai.addStringPermissions(permissions);
		return sai;
	}
	/**
	 * @see 認證查詢
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		// TODO Auto-generated method stub
		return null;
	}
}
配置ini:
############# authorization ################
myRealm2=com.fxl.Test.LearnOne.shiro.authorization.AuthoriationTest
securityManager.realms=$myRealm2

二、自定義的資源字符串實現:
須要實現3個接口:permission,permissionResolver,rolePermissionResolver 
permission:定義了字符串的 組成方式 和 對比方式
permissionResolver:根據字符串的組成方式來實現不一樣的permission對象.
rolePermissionResolver:經過不一樣的角色來獲取不一樣的permission對戲。
ps:每一permission都是一個對象實例,因此須要咱們實現permission接口,須要咱們經過組成方式實現perimission。
    eg:permission1: +資源標識符+操做+對象ID
       permission2: -資源標識符+操做+對象ID

配置的文件(ini):
#################自定義的 permission############
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer

#自定義permissionResolver  
permissionResolver=com.fxl.Test.LearnOne.shiro.authorization.MyRolePermissionReslover  
authorizer.permissionResolver=$permissionResolver  

#自定義rolePermissionResolver  
rolePermissionResolver=com.fxl.Test.LearnOne.shiro.authorization.MyPermissionReslover  
authorizer.rolePermissionResolver=$rolePermissionResolver 

securityManager.authorizer=$authorizer

        三、realm:realm算是authencation和authorization模塊的一部分。單獨拿出來是由於咱們能夠經過實現直接繼承一個authorizingRealm來實現認證和受權。

public class RealmTest extends AuthorizingRealm {
	/***
	 * @see 權限查詢
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		SimpleAuthorizationInfo sai = new SimpleAuthorizationInfo();
		// 添加角色
		sai.addRole("admim"); // 單角色
		List<String> roles = new ArrayList<String>();// 多角色
		roles.add("admin1");
		roles.add("admin2");
		sai.addRoles(roles);

		// 添加資源權限
		sai.addStringPermission("user:update");
		List<String> permissions = new ArrayList<String>();// 多角色
		permissions.add("user:create");
		permissions.add("user:delete");
		sai.addStringPermissions(permissions);
		return sai;
	}
	/**
	 * @see 認證查詢
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("myRealm");
		String userName = (String) token.getPrincipal(); // 帳戶
		String password = new String((char[]) token.getCredentials()); // 密碼
		if (!"userName".equals(userName)) {
			throw new UnknownAccountException();// 帳戶錯誤
		}
		if (!"password".equals(password)) {
			throw new IncorrectCredentialsException();// 密碼錯誤
		}
		return new SimpleAuthenticationInfo(userName, password, "myRealm");
	}
}

配置:
############# authorization ################
myRealm3=com.fxl.Test.LearnOne.shiro.authorization.RealmTest 
securityManager.realms=$myRealm2

        三、cache:因爲每一次受權、session都會查詢一次元數據(例如:從數據庫中查詢受權字符串)。很影響性能,cache就是咱們的不二之選。shiro默認使用的EHchache,固然也能夠經過實現接口來實現

緩存主要用在realm查詢和session中:
一、擴展接口:
cache:shiro不一樣模塊調用的通用接口。若是我須要本身實現cache,則須要將這些接口都換掉
CacheManager:獲取一個cache對象。實現這個接口,能夠從第三方接口中獲取cache。
CacheManagerAware:注入CacheManager,在authencation、authorization、sessionDAO中都有這個接口實現。而後經過IOC,注入咱們本身的cache。

二、默認cache:Ehcache

三、配置:
realm:認證、受權
myRealm3=com.fxl.Test.LearnOne.shiro.authorization.RealmTest 
myRealm3.credentialsMatcher=$credentialsMatcher
#######開啓cacheManager#######
myRealm3.cachingEnabled=true
myRealm3.authenticationCachingEnabled=true
myRealm3.authenticationCacheName=authenticationCache
myRealm3.authorizationCachingEnabled=true
myRealm3.authorizationCacheName=authorizationCache

securityManager.realms=$myRealm3

##########設置cacheManager################
cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml
securityManager.cacheManager=$cacheManager;

session配置cache:
##################開啓session的cacheManager#################
sessionManager=org.apache.shiro.session.mgt.DefaultSessionManager
securityManager.sessionManager=$sessionManager;

#####################實現sessionDAO的cacheManager###########
sessionDAO=com.fxl.Test.LearnOne.shiro.authorization.session.dao.MySessionDAO
sessionDAO.activeSessionsCacheName=shiro-activeSessionCache;
相關文章
相關標籤/搜索