Shiro-学习总结-认证
2017-02-20 22:19
281 查看
网上找到一张认证的相关图,如下
shiro第一个例子,参考quickstart的例子,相关文档可以去shiro官网下载
首先创建一个maven的工程,pom.xml文件内容如下:
java代码程序:
总结:
1、创建默认的securityManager,会默认注入iniRealm即表示从配置文件中获取用户相关信息。源码为:
2、用户通过currentUser.login(token)方法进行认证,内部调用securityManager.login(this, token),securityManager则是通过调用Authenticator的 public AuthenticationInfoauthenticate(AuthenticationToken
authenticationToken) throws AuthenticationException;方法进行认证。而Authenticator是一个接口,其接口实现类有如下图所示:
认证程序最终会去调用ModularRealmAuthenticator里的doAuthenticate(AuthenticationToken authenticationToken)方法【authenticationToken为用户输入的用户名,密码】。doAuthenticate方法源码如下:
之后在根据realm个数,进行不同方法的调用:
//单个realm
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
if (token != null && info != null) {
cacheAuthenticationInfoIfPossible(token, info);
}
} else {
log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
}
if (info != null) {
assertCredentialsMatch(token, info);//默认认证方法为SimpleCredentialsMatcher
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
shiro第一个例子,参考quickstart的例子,相关文档可以去shiro官网下载
首先创建一个maven的工程,pom.xml文件内容如下:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> </dependencies> <build> <finalName>shiro</finalName> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/${project.build.finalName}</path> </configuration> </plugin> </plugins> </build>
java代码程序:
public class Quickstart { private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class); public static void main(String[] args) { //构造SecurityManager Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //获取当前subject Subject currentUser = SecurityUtils.getSubject(); //获取session Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Retrieved the correct value! [" + value + "]"); } //测试当前用户是否已经登录即执行认证 if (!currentUser.isAuthenticated()) { //用户名、密码封装为UsernamePasswordToken UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); //记住我 token.setRememberMe(true); try { //登录即执行认证 currentUser.login(token); } catch (UnknownAccountException uae) {//没有此账户 log.info("There is no user with username of " + token.getPrincipal()); } catch (IncorrectCredentialsException ice) {//密码错误 log.info("Password for account " + token.getPrincipal() + " was incorrect!"); } catch (LockedAccountException lae) {//账户被锁定 log.info("The account for username " + token.getPrincipal() + " is locked. " + "Please contact your administrator to unlock it."); } catch (AuthenticationException ae) { } } log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //判断是否有某个角色 if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //判断是否有某个权限 if (currentUser.isPermitted("lightsaber:wield")) { log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } if (currentUser.isPermitted("winnebago:drive:eagle5")) { log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " + "Here are the keys - have fun!"); } else { log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); } //退出登录 currentUser.logout(); System.exit(0); } }
总结:
1、创建默认的securityManager,会默认注入iniRealm即表示从配置文件中获取用户相关信息。源码为:
protected Realm createRealm(Ini ini) { //IniRealm realm = new IniRealm(ini); changed to support SHIRO-322 IniRealm realm = new IniRealm();//默认为inirealm realm.setName(INI_REALM_NAME); realm.setIni(ini); //added for SHIRO-322 return realm; }
2、用户通过currentUser.login(token)方法进行认证,内部调用securityManager.login(this, token),securityManager则是通过调用Authenticator的 public AuthenticationInfoauthenticate(AuthenticationToken
authenticationToken) throws AuthenticationException;方法进行认证。而Authenticator是一个接口,其接口实现类有如下图所示:
认证程序最终会去调用ModularRealmAuthenticator里的doAuthenticate(AuthenticationToken authenticationToken)方法【authenticationToken为用户输入的用户名,密码】。doAuthenticate方法源码如下:
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { assertRealmsConfigured(); Collection<Realm> realms = getRealms(); if (realms.size() == 1) { return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);//单个realm } else { return doMultiRealmAuthentication(realms, authenticationToken);//多个realm } }
之后在根据realm个数,进行不同方法的调用:
//单个realm
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { if (!realm.supports(token)) { String msg = "Realm [" + realm + "] does not support authentication token [" + token + "]. Please ensure that the appropriate Realm implementation is " + "configured correctly or that the realm accepts AuthenticationTokens of this type."; throw new UnsupportedTokenException(msg); } AuthenticationInfo info = realm.getAuthenticationInfo(token); if (info == null) { String msg = "Realm [" + realm + "] was unable to find account data for the " + "submitted AuthenticationToken [" + token + "]."; throw new UnknownAccountException(msg); } return info; }
//多个realm
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) { AuthenticationStrategy strategy = getAuthenticationStrategy(); AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token); if (log.isTraceEnabled()) { log.trace("Iterating through {} realms for PAM authentication", realms.size()); } for (Realm realm : realms) { aggregate = strategy.beforeAttempt(realm, token, aggregate); if (realm.supports(token)) { log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm); AuthenticationInfo info = null; Throwable t = null; try { info = realm.getAuthenticationInfo(token); } catch (Throwable throwable) { t = throwable; if (log.isDebugEnabled()) { String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:"; log.debug(msg, t); } } aggregate = strategy.afterAttempt(realm, token, info, aggregate, t); } else { log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token); } } aggregate = strategy.afterAllAttempts(token, aggregate); return aggregate; }无论单个还是多个realm都会调用realm.getAuthenticationInfo(token),此时的realm默认为org.apache.shiro.realm.SimpleAccountRealm。代码如下:
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
if (token != null && info != null) {
cacheAuthenticationInfoIfPossible(token, info);
}
} else {
log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
}
if (info != null) {
assertCredentialsMatch(token, info);//默认认证方法为SimpleCredentialsMatcher
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
相关文章推荐
- Shiro学习总结(3)——Apache Shiro身份认证
- Shiro学习总结(3)——Apache Shiro身份认证
- Shiro-学习总结-认证之自定义realm
- shiro学习_总结
- shiro学习之认证
- Shiro学习随笔【二】身份认证
- Shiro学习随笔【二】身份认证
- Spring Cloud与微服务学习总结(5)——认证鉴权与API权限控制在微服务架构中的设计与实现(三)
- shiro学习之后——认证
- Shiro学习总结(10)——Spring集成Shiro
- SpringBoot+shiro整合学习之登录认证和权限控制
- shiro基础学习(二)—shiro认证
- Shiro学习随笔【二】身份认证
- Shiro学习随笔【二】身份认证
- Spring Cloud与微服务学习总结(3)——认证鉴权与API权限控制在微服务架构中的设计与实现(一)
- Spring Cloud与微服务学习总结(6)——认证鉴权与API权限控制在微服务架构中的设计与实现(四)
- Shiro 学习笔记(1)-Helloworld 和 身份认证
- Apache shiro学习总结
- SpringBoot+shiro整合学习之登录认证和权限控制
- shiro学习和使用实例(2)——登陆认证和授权