Shiro回话管理和加密

会话管理的相关API

Shiro提供了丰富的会话管理API,允许开发者对会话进行创建、获取、设置属性、删除属性、获取会话超时时间、设置会话超时时间等操作。

  • Subject.getSession():获取当前用户的会话。如果当前没有会话,则会创建一个新的会话。
  • Session.setAttribute(key, value):设置会话属性。
  • Session.getAttribute(key):获取会话属性。
  • Session.removeAttribute(key):删除会话属性。
  • Session.getTimeout():获取当前会话的超时时间(以毫秒为单位)。
  • Session.setTimeout(timeout):设置当前会话的超时时间(以毫秒为单位)。

SessionDAO和会话的使用

SessionDAO是用于会话持久化的接口,Shiro提供了多种SessionDAO实现,如MemorySessionDAO(在内存中进行会话维护)、EnterpriseCacheSessionDAO(提供缓存功能的会话维护)等。

  • Serializable create(Session session):将一个新的会话持久化到存储设备。
  • Session readSession(Serializable sessionId):根据会话ID从存储设备中获取会话。
  • void update(Session session):更新会话信息,如更新会话的最后访问时间、设置超时时间等。
  • void delete(Session session):删除会话。

在实际应用中,可以通过配置Shiro的sessionManager和sessionDAO来实现会话的持久化和管理。

缓存的问题分析和解决办法

在使用Shiro进行会话管理时,可能会遇到缓存相关的问题,如缓存失效、缓存不一致等。这些问题通常是由于缓存配置不当或缓存实现不支持某些操作导致的。

  • 问题分析

    1. 缓存失效:可能是由于缓存过期策略设置不当或缓存被手动清除导致的。
    2. 缓存不一致:可能是由于多个线程同时修改缓存数据而没有进行同步导致的。
  • 解决办法

    1. 确保缓存过期策略设置合理,避免缓存过早失效。
    2. 使用线程安全的缓存实现,或在修改缓存数据时进行同步处理。
    3. 定期检查缓存状态,及时发现并处理缓存问题。

Shiro加密功能

加密哈希与盐

为了保护用户密码等敏感信息,Shiro提供了加密哈希与盐的功能。通过哈希函数(如MD5、SHA-256等)和盐值(一个随机生成的字符串)的组合,可以将用户密码转换为不可逆的哈希值,从而确保密码在存储过程中的安全性。

加密与验证

在Shiro中,可以使用HashedCredentialsMatcher类来实现密码的加密与验证。该类提供了对密码进行哈希处理的功能,并在用户登录时验证输入的密码是否与存储的哈希值匹配。

  • 加密实现

在用户注册时,使用HashedCredentialsMatcher对密码进行哈希处理,并将哈希值和盐值存储在数据库中。

java 复制代码
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();  
matcher.setHashAlgorithmName("SHA-256"); // 设置哈希算法  
matcher.setHashIterations(1024); // 设置哈希迭代次数
  • 验证实现

在用户登录时,从数据库中获取用户的哈希值和盐值,并使用HashedCredentialsMatcher对输入的密码进行哈希处理。然后,比较处理后的哈希值是否与数据库中的哈希值匹配。

java 复制代码
AuthenticationInfo info = new SimpleAuthenticationInfo(username, hashedPassword, salt, realmName);  
// ... 在登录验证过程中使用info对象进行密码比对

登录次数的限制

为了防止恶意用户通过暴力破解密码的方式攻击系统,Shiro提供了登录次数的限制功能。可以通过配置Shiro的Realm或自定义拦截器来实现该功能。

  • 实现思路

    1. 使用缓存(如Redis或Ehcache)来记录用户的登录次数。
    2. 在用户登录时,检查缓存中记录的登录次数是否超过限制。
    3. 如果超过限制,则拒绝用户的登录请求,并设置一定的锁定时间。
    4. 如果未超过限制,则允许用户登录,并更新缓存中的登录次数。
  • 示例代码

以下是一个使用Redis实现登录次数限制的示例代码:

java 复制代码
// 自定义拦截器  
public class LoginAttemptLimitFilter extends AccessControlFilter {  
    // ...  
      
    @Override  
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {  
        // 从请求中获取用户名  
        String username = (String) request.getAttribute("username");  
          
        // 从Redis中获取用户的登录次数  
        Jedis jedis = new Jedis("localhost");  
        String loginAttempts = jedis.get("loginAttempts:" + username);  
          
        if (loginAttempts != null && Integer.parseInt(loginAttempts) >= 5) {  
            // 登录次数超过限制,拒绝访问  
            return false;  
        }  
          
        // 允许访问,并更新登录次数  
        if (loginAttempts == null) {  
            jedis.set("loginAttempts:" + username, "1");  
        } else {  
            jedis.incr("loginAttempts:" + username);  
        }  
          
        return true;  
    }  
      
    // ...  
}  
  
// Shiro配置类  
@Configuration  
public class ShiroConfig {  
    // ...  
      
    @Bean  
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {  
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();  
        shiroFilter.setSecurityManager(securityManager);  
          
        // 配置登录URL、成功URL和未授权URL  
        shiroFilter.setLoginUrl("/login");  
        shiroFilter.setSuccessUrl("/home");  
        shiroFilter.setUnauthorizedUrl("/403");  
          
        // 配置自定义拦截器  
        Map<String, Filter> filters = new HashMap<>();  
        filters.put("loginAttemptLimit", new LoginAttemptLimitFilter());  
        shiroFilter.setFilters(filters);  
          
        // 配置URL过滤链  
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();  
        filterChainDefinitionMap.put("/login", "anon");  
        filterChainDefinitionMap.put("/**", "authc, loginAttemptLimit");  
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);  
          
        return shiroFilter;  
    }  
      
    // ...  
}
相关推荐
等一场春雨5 分钟前
Java 23 集合框架详解:ArrayList、LinkedList、Vector
java·开发语言
Hello Dam7 分钟前
分布式环境下定时任务扫描时间段模板创建可预订时间段
java·定时任务·幂等性·redis管道·mysql流式查询
javaweiming7 分钟前
根据中文名称首字母进行分组
java·汉字转拼音
桂月二二1 小时前
深入探索 Rust 中的异步编程:从基础到实际案例
开发语言·后端·rust
杂货铺的小掌柜3 小时前
spring mvc源码学习笔记之六
学习·spring·mvc
心之语歌5 小时前
Spring boot 项目 Spring 注入 代理 并支持 代理对象使用 @Autowired 去调用其他服务
spring boot·后端·spring
水宝的滚动歌词6 小时前
设计模式之建造者模式
java·设计模式·建造者模式
孤蓬&听雨6 小时前
Java SpringBoot使用Apache POI导入导出Excel文件
java·spring boot·apache·excel导出·excel导入
自律小仔6 小时前
桌面开发 的变量声明(Variable Declaration)核心知识
开发语言·后端·golang
紫琪软件工作室7 小时前
自定义有序Map
java