日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Shiro源码学习之二

發(fā)布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Shiro源码学习之二 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

接上一篇?Shiro源碼學(xué)習(xí)之一

3.subject.login



進入login

public void login(AuthenticationToken token) throws AuthenticationException {clearRunAsIdentitiesInternal();Subject subject = securityManager.login(this, token);PrincipalCollection principals;String host = null;if (subject instanceof DelegatingSubject) {DelegatingSubject delegating = (DelegatingSubject) subject;//we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:principals = delegating.principals;host = delegating.host;} else {principals = subject.getPrincipals();}if (principals == null || principals.isEmpty()) {String msg = "Principals returned from securityManager.login( token ) returned a null or " +"empty value.  This value must be non null and populated with one or more elements.";throw new IllegalStateException(msg);}this.principals = principals;this.authenticated = true;if (token instanceof HostAuthenticationToken) {host = ((HostAuthenticationToken) token).getHost();}if (host != null) {this.host = host;}Session session = subject.getSession(false);if (session != null) {this.session = decorate(session);} else {this.session = null;}}

private void clearRunAsIdentitiesInternal() {//try/catch added for SHIRO-298try {clearRunAsIdentities();} catch (SessionException se) {log.debug("Encountered session exception trying to clear 'runAs' identities during logout.  This " +"can generally safely be ignored.", se);}}

private void clearRunAsIdentities() {Session session = getSession(false);if (session != null) {session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);}}


Session接口
public interface Session {
Serializable getId();
...


第一次直接return null

public Session getSession(boolean create) {
...
if (this.session == null && create) {
...
SessionContext sessionContext = createSessionContext();Session session = this.securityManager.start(sessionContext);this.session = decorate(session);}return this.session;

回到clearRunAsIdentitiesInternal



回到login



securityManager是DelegatingSubject聲明的protected transient SecurityManager無序序列化



java的transient關(guān)鍵字為我們提供了便利,你只需要實現(xiàn)Serilizable接口,將不需要序列化的屬性前添加關(guān)鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。

java transient簡介


進入public Subject login(Subject subject, AuthenticationToken token)



進入public AuthenticationInfo authenticate(AuthenticationToken token)

public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {return this.authenticator.authenticate(token);}


進入public final AuthenticationInfo authenticate(AuthenticationToken token)

public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {if (token == null) {throw new IllegalArgumentException("Method argumet (authentication token) cannot be null.");}log.trace("Authentication attempt received for token [{}]", token);AuthenticationInfo info;try {info = doAuthenticate(token);if (info == null) {String msg = "No account information found for authentication token [" + token + "] by this " +"Authenticator instance.  Please check that it is configured correctly.";throw new AuthenticationException(msg);}} catch (Throwable t) {AuthenticationException ae = null;if (t instanceof AuthenticationException) {ae = (AuthenticationException) t;}if (ae == null) {//Exception thrown was not an expected AuthenticationException.  Therefore it is probably a little more//severe or unexpected.  So, wrap in an AuthenticationException, log to warn, and propagate:String msg = "Authentication failed for token submission [" + token + "].  Possible unexpected " +"error? (Typical or expected login exceptions should extend from AuthenticationException).";ae = new AuthenticationException(msg, t);}try {notifyFailure(token, ae);} catch (Throwable t2) {if (log.isWarnEnabled()) {String msg = "Unable to send notification for failed authentication attempt - listener error?.  " +"Please check your AuthenticationListener implementation(s).  Logging sending exception " +"and propagating original AuthenticationException instead...";log.warn(msg, t2);}}throw ae;}log.debug("Authentication successful for token [{}].  Returned account [{}]", token, info);notifySuccess(token, info);return info;}



進入protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)


protected void assertRealmsConfigured() throws IllegalStateException {



IllegalStateException異常:


protected Collection<Realm> getRealms() {return this.realms;}


回到doAuthenticate



進入doSingleRealmAuthentication




進入getCachedAuthenticationInfo


getAvailableAuthenticationCache返回null



回到getCachedAuthenticationInfo返回info是null

回到getAuthenticationInfo


進入doGetAuthenticationInfo



進入getUser用到了lock與unlock

USERS_LOCK.readLock().lock();try {return this.users.get(username);} finally {USERS_LOCK.readLock().unlock();}



參考:Java中鎖的應(yīng)用之-Lock



public boolean isCredentialsExpired() {return credentialsExpired;}
account.isCredentialsExpired()返回flase

doGetAuthenticationInfo返回account


回到getAuthenticationInfo

cacheAuthenticationInfoIfPossible

private void cacheAuthenticationInfoIfPossible(AuthenticationToken token, AuthenticationInfo info) {if (!isAuthenticationCachingEnabled(token, info)) {log.debug("AuthenticationInfo caching is disabled for info [{}].  Submitted token: [{}].", info, token);//return quietly, caching is disabled for this token/info pair:return;}Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();if (cache != null) {Object key = getAuthenticationCacheKey(token);cache.put(key, info);log.trace("Cached AuthenticationInfo for continued authentication.  key=[{}], value=[{}].", key, info);}}
回到getAuthenticationInfo

進入assertCredentialsMatch

進入doCredentialsMatch

進入protected boolean equals(Object tokenCredentials, Object accountCredentials)

順便提到一點public static boolean equals(byte[] a, byte[] a2)已經(jīng)是java.util的class Arrays了

public static boolean equals(byte[] a, byte[] a2) {if (a==a2)return true;if (a==null || a2==null)return false;int length = a.length;if (a2.length != length)return false;for (int i=0; i<length; i++)if (a[i] != a2[i])return false;return true;}

回到getAuthenticationInfo


回到doSingleRealmAuthentication


回到protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)


回到public final AuthenticationInfo authenticate(AuthenticationToken token)


代碼走到notifySuccess(token, info);



protected void notifySuccess(AuthenticationToken token, AuthenticationInfo info)因為listeners的size=0所以直接跳出此方法



回到public final AuthenticationInfo authenticate(AuthenticationToken token)


回到public AuthenticationInfo authenticate(AuthenticationToken token)



回到public Subject login(Subject subject, AuthenticationToken token)


進入protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing)


進入public Subject createSubject(SubjectContext subjectContext)


protected SubjectContext copy(SubjectContext subjectContext) {return new DefaultSubjectContext(subjectContext);}

public DefaultSubjectContext(SubjectContext ctx) {super(ctx);}


運行到this.backingMap.putAll(map);


回到public Subject createSubject(SubjectContext subjectContext)


protected SubjectContext ensureSecurityManager(SubjectContext context)


回到public Subject createSubject(SubjectContext subjectContext)


進入protected SubjectContext resolveSession(SubjectContext context)


protected SessionKey getSessionKey(SubjectContext context) {Serializable sessionId = context.getSessionId();if (sessionId != null) {return new DefaultSessionKey(sessionId);}return null;}
Serializable sessionId =null直接返回。

回到protected SubjectContext resolveSession(SubjectContext context)


又回到public Subject createSubject(SubjectContext subjectContext)



進入protected SubjectContext resolvePrincipals(SubjectContext context)由于principals不為空直接返回了


 @SuppressWarnings({"unchecked"})protected SubjectContext resolvePrincipals(SubjectContext context) {PrincipalCollection principals = context.resolvePrincipals();if (CollectionUtils.isEmpty(principals)) {log.trace("No identity (PrincipalCollection) found in the context.  Looking for a remembered identity.");principals = getRememberedIdentity(context);if (!CollectionUtils.isEmpty(principals)) {log.debug("Found remembered PrincipalCollection.  Adding to the context to be used " +"for subject construction by the SubjectFactory.");context.setPrincipals(principals);} else {log.trace("No remembered identity found.  Returning original context.");}}return context;}


又回到public Subject createSubject(SubjectContext subjectContext)?


protected Subject doCreateSubject(SubjectContext context) {return getSubjectFactory().createSubject(context);}
public SubjectFactory getSubjectFactory() {return subjectFactory;}


進入public Subject createSubject(SubjectContext context)

public DelegatingSubject(PrincipalCollection principals, boolean authenticated, String host,Session session, boolean sessionCreationEnabled, SecurityManager securityManager)


回到createSubject,回到doCreateSubject,最后回到public Subject createSubject(SubjectContext subjectContext)


protected void save(Subject subject) {this.subjectDAO.save(subject);}

protected void saveToSession(Subject subject) {//performs merge logic, only updating the Subject's session if it does not match the current state:mergePrincipals(subject);mergeAuthenticationState(subject);}
protected void mergePrincipals(Subject subject) {//merge PrincipalCollection state:PrincipalCollection currentPrincipals = null;//SHIRO-380: added if/else block - need to retain original (source) principals//This technique (reflection) is only temporary - a proper long term solution needs to be found,//but this technique allowed an immediate fix that is API point-version forwards and backwards compatible////A more comprehensive review / cleaning of runAs should be performed for Shiro 1.3 / 2.0 +if (subject.isRunAs() && subject instanceof DelegatingSubject) {try {Field field = DelegatingSubject.class.getDeclaredField("principals");field.setAccessible(true);currentPrincipals = (PrincipalCollection)field.get(subject);} catch (Exception e) {throw new IllegalStateException("Unable to access DelegatingSubject principals property.", e);}}if (currentPrincipals == null || currentPrincipals.isEmpty()) {currentPrincipals = subject.getPrincipals();}Session session = subject.getSession(false);if (session == null) {if (!CollectionUtils.isEmpty(currentPrincipals)) {session = subject.getSession();session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, currentPrincipals);}//otherwise no session and no principals - nothing to save} else {PrincipalCollection existingPrincipals =(PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);if (CollectionUtils.isEmpty(currentPrincipals)) {if (!CollectionUtils.isEmpty(existingPrincipals)) {session.removeAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);}//otherwise both are null or empty - no need to update the session} else {if (!currentPrincipals.equals(existingPrincipals)) {session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, currentPrincipals);}//otherwise they're the same - no need to update the session}}}
protected void mergeAuthenticationState(Subject subject) {Session session = subject.getSession(false);if (session == null) {if (subject.isAuthenticated()) {session = subject.getSession();session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, Boolean.TRUE);}//otherwise no session and not authenticated - nothing to save} else {Boolean existingAuthc = (Boolean) session.getAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);if (subject.isAuthenticated()) {if (existingAuthc == null || !existingAuthc) {session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, Boolean.TRUE);}//otherwise authc state matches - no need to update the session} else {if (existingAuthc != null) {//existing doesn't match the current state - remove it:session.removeAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);}//otherwise not in the session and not authenticated - no need to update the session}}}
public void setAttribute(Object attributeKey, Object value)




private Session lookupSession(SessionKey key) throws SessionException {if (key == null) {throw new NullPointerException("SessionKey argument cannot be null.");}return doGetSession(key);}


protected void validate(Session session, SessionKey key) throws InvalidSessionException {try {doValidate(session);} catch (ExpiredSessionException ese) {onExpiration(session, ese, key);throw ese;} catch (InvalidSessionException ise) {onInvalidation(session, ise, key);throw ise;}}
protected void doValidate(Session session) throws InvalidSessionException {if (session instanceof ValidatingSession) {((ValidatingSession) session).validate();} else {String msg = "The " + getClass().getName() + " implementation only supports validating " +"Session implementations of the " + ValidatingSession.class.getName() + " interface.  " +"Please either implement this interface in your session implementation or override the " +AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";throw new IllegalStateException(msg);}}

回到public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value)


protected void onChange(Session session) {sessionDAO.update(session);}
public void update(Session session) throws UnknownSessionException {storeSession(session.getId(), session);}

這已經(jīng)是系統(tǒng)級的代碼了java.util.concurrent

參考:HashMap和ConcurrentHashMap研究

回到protected void mergeAuthenticationState(Subject subject)


回到saveToSession

回到public Subject save(Subject subject)


回到protected void save(Subject subject)


回到public Subject createSubject(SubjectContext subjectContext)


回到protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing)


回到public Subject login(Subject subject, AuthenticationToken token)?


進入protected void onSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject)


進入protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject)

RememberMeManager rmm =null直接返回了


又回到public Subject login(Subject subject, AuthenticationToken token)


回到外層public void login(AuthenticationToken token)


繼續(xù)往下


進入protected Session decorate(Session session)


進入private StoppingAwareProxiedSession(Session target, DelegatingSubject owningSubject)


回到public void login(AuthenticationToken token)


終于回到最外層調(diào)用代碼



4.subject.getPrincipal()

logger.info("登錄成功!Hello " + subject.getPrincipal());
public Object getPrincipal() {return getPrimaryPrincipal(getPrincipals());}


5.subject.logout();

public void logout() {try {clearRunAsIdentitiesInternal();this.securityManager.logout(this);} finally {this.session = null;this.principals = null;this.authenticated = false;//Don't set securityManager to null here - the Subject can still be//used, it is just considered anonymous at this point.  The SecurityManager instance is//necessary if the subject would log in again or acquire a new session.  This is in response to//https://issues.apache.org/jira/browse/JSEC-22//this.securityManager = null;}}
private void clearRunAsIdentitiesInternal() {//try/catch added for SHIRO-298try {clearRunAsIdentities();} catch (SessionException se) {log.debug("Encountered session exception trying to clear 'runAs' identities during logout.  This " +"can generally safely be ignored.", se);}}
private void clearRunAsIdentities() {Session session = getSession(false);if (session != null) {session.removeAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);}}
public Object removeAttribute(Object key) throws InvalidSessionException {return delegate.removeAttribute(key);}
public Object removeAttribute(Object attributeKey) throws InvalidSessionException {return sessionManager.removeAttribute(this.key, attributeKey);}

調(diào)用系統(tǒng)級的remove方法。



總結(jié)

以上是生活随笔為你收集整理的Shiro源码学习之二的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。