用户的信息多都在Realm中,所以我们先从realm开始看源码吧。
我们在上一篇中用到了AuthenticationRealm,这个就是Realm接口的实现类,我们具体看这个类的源码以及在校验时所用到的方法。
先从这个类的无参构造方法开始
public AuthenticatingRealm() {
this(null, new SimpleCredentialsMatcher());
}
其中第一个参数是CacheManager,是一个null,第二个是CredentialsMatcher。AuthenticationRealm是CachingRealm的实现类,CachingRealm允许对将用户已经获得AuthenticationIfon进行缓存,方便下一次使用。但是这个缓存默认是关闭的,AuthenticationRealm构造方法中的null表示没有传入CaqcheManager,我们在实际开发中都是关闭缓存,改用redis来实现对用户信息的缓存。
第二个参数CredentialsMatcher很重要,他用来将用户通过表单提交的密码和在数据库中的密码进行比对,判断是不是一直,默认提供的实现类是SimpleCredentialsMatcher,这个类的对比方式如下:
protected boolean equals(Object tokenCredentials, Object accountCredentials) {
if (log.isDebugEnabled()) {
log.debug("Performing credentials equality check for tokenCredentials of type [" +
tokenCredentials.getClass().getName() + " and accountCredentials of type [" +
accountCredentials.getClass().getName() + "]");
}
if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
if (log.isDebugEnabled()) {
log.debug("Both credentials arguments can be easily converted to byte arrays. Performing " +
"array equals comparison");
}
byte[] tokenBytes = toBytes(tokenCredentials);
byte[] accountBytes = toBytes(accountCredentials);
return Arrays.equals(tokenBytes, accountBytes);
} else {
return accountCredentials.equals(tokenCredentials);
}
}
我们一般采用字符串作为密码,假设这样的话,会将字符串转化为数组,采用的办法是
String.getBytes("UTF-8")
然后调用Arrays.equals的方法。从这里我们看出,SimpleCredentialsMatcher没有涉及任何的加密算法,只适合于我们的普通测试字符串是否相同,如果是加密的我们需要自己定义自己的加密算法和使用加密算法进行对比的CredentialMatcher,但是在实际中我们更倾向于这样做:
在数据库中存储的是经过加密的密码,将用户提交的密码在进行对比之前我们自己使用相同的办法将其进行加密,然后仍然使用SimpleCredentialsMatcher,这样就避免了创建CredentialMatcher的麻烦了。在接触shiro前我的加密算法都是采用的md5 + base64,幸运的是shiro也提供了这两种加密算法,我推荐搭建使用shiro自带的加密类,然后将其封装成一个工具类,我的代码如下:
import org.apache.shiro.crypto.hash.Md5Hash;
public class EncryptUtil {
public String toMd5(String pwd){
return new Md5Hash(pwd,"salt2016",111).toBase64();
}
}
shiro提供了Hash接口,表示对明文加密,其中Md5Hash只是个例(这个不是重点,也可以使用Md2Hash) 具体解释如下:org.apache.shiro.crypto.hash.Md5Hash.Md5Hash(Object source, Object salt, int encryptionTime) 第一个参数表示要加密的密码,第二个表示加密过程中加的盐,第三个表示加密的次数,也就是明文加密一次后再对新生成的暗纹继续加密,还有很多重载的Md5Hash构造方法,并且可以不用加盐,也不用指定加密的次数。最后toBase64是用来格式化显示的,因为调用md5加密算法之后会有一些不友好的字符,通过base64将其完全转化为键盘上的字符,这样更加友好。(也可以toHex,只是算法不同,意思一样)
继续我们的AuthenticatingRealm 在另一个构造方法中 AuthenticatingRealm(CacheManager, CredentialsMatcher),我们看一下源码
public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
authenticationTokenClass = UsernamePasswordToken.class;
//retain backwards compatibility for Shiro 1.1 and earlier. Setting to true by default will probably cause
//unexpected results for existing applications:
this.authenticationCachingEnabled = false;
int instanceNumber = INSTANCE_COUNT.getAndIncrement();
this.authenticationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
if (instanceNumber > 0) {
this.authenticationCacheName = this.authenticationCacheName + "." + instanceNumber;
}
if (cacheManager != null) {
setCacheManager(cacheManager);
}
if (matcher != null) {
setCredentialsMatcher(matcher);
}
}
其中指定了默认支持的AuthenticationTokenClass是UsernamePassowrdToken,所以我们在上一节的代码中使用了UsernamePasswordToken,如果不适用这个的话必须改对AuthenticationReal进行设置,否则会不支持的。从这个代码中发现默认是不支持缓存的,所以关于缓存的我们就可以放心了。然后在这个构造方法中设置了CredentialsMather,就是上面介绍的SimpleCredentialsMatcher。
当某个用户登录时,通过dubug发现调用的是AuthenticatingRealm的getAuthenticationInfo方法,就是通过传入的UsernamePasswordToken,将源码拿出来
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);
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
上面代码的 大致意思是先从以前缓存的获取,因为我们不做缓存,所以忽略这个,如果缓存中没有的话调用的是doGetAuthenticationInfo(token)方法,这个就是我们上一节中覆写的方法,用来从数据库中获得用户的信息。最后assertCredentialsMatcher调用之前设置的CredentialMatcher进行对比传递进来的token和最后从数据库中获取的info是否一致,我们看一下assertCredentialsMatcher方法的源码:
相关推荐
该资源是目前最新的shiro-core核心包,暂时魏安全性较高的版本,没有发现漏洞版本。提供登录安全性的校验,该资源来自官网,仅供学习参考,请前往官网下载
通过这两个模块,开发者可以学习如何在实际项目中集成和配置Shiro、JWT以及OAuth2.0,以实现安全且灵活的权限认证。这不仅有助于提高系统的安全性,还能提升用户体验,因为用户只需要登录一次即可访问多个受保护的...
4. **过滤器配置**:Shiro通过Filter链来实现安全控制,如登录拦截、权限校验等。在JFinal中,我们通常会看到对应的ShiroFilter配置,用于定义哪些URL需要经过Shiro的处理。 5. **数据库集成**:JDBC的使用意味着...
总之,Apache Shiro 1.4.0-RC2的示例代码为你提供了一手的实践经验,帮助你深入学习和掌握这个安全框架的各个方面。从身份认证到授权,再到加密和会话管理,每个示例都是一次探索Shiro特性的机会。通过研究这些示例...
在本案例中,Shiro主要用来实现用户权限的管理,如登录验证、角色分配和权限校验。你可以通过Shiro的过滤器链来定义哪些URL需要用户登录才能访问,哪些操作需要特定的角色权限。 **MyBatis-Plus** MyBatis-Plus是在...
通过上述知识点的学习,Java开发者及相关专业和技术爱好者将能够深入理解Shiro框架的核心概念与工作原理,并能够运用到实际项目开发中,实现用户认证、授权、加密等功能,从而提升项目的整体安全性和用户体验。
"shiro登录拦截校验demo"是一个实际应用Shiro框架进行登录验证和权限拦截的示例项目。 在该demo中,我们可以学习到以下几个核心知识点: 1. **Shiro的基本概念**: - **身份验证(Authentication)**:确认用户...
通过这个案例,开发者可以学习到如何在实际项目中结合SSM和Shiro,实现一个完整的用户登录功能。这不仅涉及到了前后端交互、数据库操作,还涵盖了权限管理和会话控制等核心安全概念。理解并掌握这些知识,对于提升...
在"shiro学习示例"中,我们可以深入理解Shiro的核心概念和实际应用。 1. **Shiro基本概念** - **认证**:确认用户身份的过程,即用户输入用户名和密码,系统通过验证来确认用户的身份。 - **授权**:确定用户是否...
5. **编写Controller**:在Controller层,Shiro会自动处理登录、登出等操作。你可以使用`@ShiroSubject`注解来访问Subject对象,进行权限检查。 6. **权限注解**:Shiro提供了一系列的注解,如`@...
1. **Filter配置**:Shiro通过Web Filter实现安全控制,我们需要在`web.xml`中配置Shiro的过滤器,如`FormAuthenticationFilter`用于表单登录,`AuthorizationFilter`用于权限校验。 2. ** Realm配置**:在Spring ...
2. Shiro 的 `FormAuthenticationFilter` 捕获请求,校验凭证。 3. 如果凭证有效,`Subject` 对象进行认证,通过 Realm 获取用户信息。 4. 如果认证成功,用户被标记为已登录状态,会话中存储相关信息。 授权则涉及...
开发者可以通过Shiro的API来定制登录、注销、权限校验等逻辑,实现灵活的安全策略。 EasyUI则是一个基于jQuery的前端框架,提供了丰富的UI组件,如表格、树形控件、下拉框等,大大简化了前端页面的开发。在本项目中...
Realm 是Shiro与应用程序数据源交互的桥梁,负责处理用户的登录验证和权限校验。 3. 创建Realm 在SpringBoot项目中,我们通常会创建自定义的Realm类,继承自`AuthorizingRealm`,并重写其`...
2. 配置Shiro Realm,实现用户和权限的获取。 3. 配置Shiro的SecurityManager,与Spring Boot整合。 4. 创建Shiro过滤器链,定义URL拦截规则。 5. 在Controller层使用Shiro的注解(如`@RequiresPermissions`)进行...
Shiro 的身份认证过程包括认证发起、凭证匹配、权限校验等步骤。用户提交用户名和密码等凭证后,Shiro 会与事先存储的凭证进行比对,如果匹配成功,就认为用户已通过身份验证。Shiro 支持多种凭证类型,如简单的...
2. **Spring Boot集成Shiro** - 在`pom.xml`中添加Shiro的依赖。 - 配置Shiro Realm,实现认证和授权逻辑。 Realm是Shiro与应用的持久层交互的接口,你需要自定义 Realm 类并实现获取用户信息、验证用户凭证的方法...
2) Shiro通过Subject进行登录尝试。 3) Shiro调用Realm进行身份验证, Realm会从数据源查询用户信息并与提交的凭证进行匹配。 4) 验证成功后,Shiro创建一个基于当前Subject的安全会话。 **4. 授权机制** Shiro的...
Shiro(Apache Shiro)是一个强大且易于使用的Java安全框架,用于身份验证、授权、加密和会话管理等安全功能。它提供了简单的API和灵活的配置选项,可以方便地集成到现有的Java应用程序中。 Shiro的主要特点包括: ...
- **shiro资料笔记与核心单词**:用户的学习笔记,可能涵盖了关键概念和常用API,是学习Shiro的好帮手。 在实际应用中,Shiro可以通过简单的配置实现用户的登录、权限检查、会话管理等功能。通过 Realm,我们可以...