Springboot(2.0)整合shiro 配置EnCache,remember me和密码校验次数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/c_royi/article/details/82015039

Springboot(2.0)整合shiro 配置EnCache,remember me和密码校验次数

配置时,请先阅读springboot整合shiro文章,
项目github地址:https://github.com/Plumblumpb/springboot-2.0–shiro.git

encache

由于每次的授权shiro都会重新范围数据库,导致查询频繁所以使用EnCache进行缓存
重点:记得将要缓存的类序列化

1.1配置maven

        <!--cache-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!--EhCache作为缓存-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>

1.2配置shirConfig

    @Bean
    public EhCacheManager ehCacheManager(){
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:config/ehcache.xml");
        return cacheManager;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        //设置Realm,用于获取认证凭证
        securityManager.setRealm(userRealm());
        //注入缓存管理器
        securityManager.setCacheManager(ehCacheManager());
        //注入Cookie(记住我)管理器(remenberMeManager)
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

1.3配置EnCached.xml

(具体看github,这个不全)

    <!-- 登录记录缓存 -->
    <cache name="passwordRetryCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

remember me

1.1配置shiroConfig

@Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //如果httyOnly设置为true,则客户端不会暴露给客户端脚本代码,使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击;
        simpleCookie.setHttpOnly(true);
        //记住我cookie生效时间,默认30天 ,单位秒:60 * 60 * 24 * 30
        simpleCookie.setMaxAge(259200);

        return simpleCookie;
    }

    /**
     * cookie管理器;
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        //rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位),通过以下代码可以获取
        //KeyGenerator keygen = KeyGenerator.getInstance("AES");
        //SecretKey deskey = keygen.generateKey();
        //System.out.println(Base64.encodeToString(deskey.getEncoded()));
        byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
        cookieRememberMeManager.setCipherKey(cipherKey);
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

并加入securityManager

1.2配置Controller

这里写图片描述

密码校验次数

1.2配置RetryLimitCredentialsMatcher

继承HashedCredentialsMatcher,并修改密码验证的流程


/**
 * @Auther: cpb
 * @Date: 2018/8/14 11:09
 * @Description:
 */
public class RetryLimitCredentialsMatcher extends  HashedCredentialsMatcher {

    private static final Logger logger = LoggerFactory.getLogger(RetryLimitCredentialsMatcher.class);

    //集群中可能会导致出现验证多过5次的现象,因为AtomicInteger只能保证单节点并发
    private Cache<String,AtomicInteger> passwordRetryCache;

    //最大校验次数。
    private int maxRetryCount = 3;


    public RetryLimitCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }


    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String) token.getPrincipal();
        //retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if (null == retryCount) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if (retryCount.incrementAndGet() > 3) {
            logger.warn("用户: " + username + " tried to login more than 3 times in period");
            throw new ExcessiveAttemptsException("用户名: " + username + " tried to login more than 3 times in period"
            );
        }
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            //clear retry data
            passwordRetryCache.remove(username);
        }
        return matches;
    }
}

1.2配置shiroConfig

    /**
     * 凭证匹配器
     * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     * )
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
//        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        HashedCredentialsMatcher hashedCredentialsMatcher = new RetryLimitCredentialsMatcher(ehCacheManager());
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }

猜你喜欢

转载自blog.csdn.net/c_royi/article/details/82015039