shiro源码分析篇3:用户登录缓存登录信息

上篇讲了shiro是如何过滤请求链接,判断用户是否已经登录。

这篇就是讲解shiro用户登录时,如何把登录信息缓存起来,下次用户登录其他需要登录的链接时,如何判断已经登录了。

RetryLimitHashedCredentialsMatcher自定义的登录凭据,也就是登录的处理方案

public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
   

    private Logger logger = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(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(retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if(retryCount.incrementAndGet() > 5) {
            //if retry count > 5 throw
            logger.info("===========尝试超过5次==============");
            throw new ExcessiveAttemptsException();
        }

        boolean matches = super.doCredentialsMatch(token, info);
        if(matches) {
            //clear retry count
            passwordRetryCache.remove(username);
        }
        return matches;
    }
}

UserRealm:Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;

UserController:用户登录功能

@Controller
public class UserController {
   
   @RequestMapping("DoLogin")
    public ModelAndView login(String username,String password){

        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()){
            return new ModelAndView("admin");
        }
        try {
            subject.login(token);
            if(subject.isAuthenticated()){
                return new ModelAndView("admin");
            }
        }catch (Exception e){

        }
        return new ModelAndView("login");
    }
}

源码请点击:https://github.com/smallleaf/cacheWeb

浏览器输入http://localhost:8080/DoLogin?username=admin&password=admin

断点打到DelegatingFilterProxy.doFilter。和UserController.login
我们走起
请求肯定是会先经过DelegatingFilterProxy进行shiro过滤的过滤功能的。和上篇一样。
这里我们分析,为什么没有登录的时候。subject.getPrincipal() ==null。

我们debug进入AbstractShiroFIlter.doFilterInternal。
final Subject subject = createSubject(request, response);
最后进入

 public Subject createSubject(SubjectContext subjectContext) {
        //create a copy so we don't modify the argument's backing map:
        SubjectContext context = copy(subjectContext);

        //ensure that the context has a SecurityManager instance, and if not, add one:
        context = ensureSecurityManager(context);

        //Resolve an associated Session (usually based on a referenced session ID), and place it in the context before
        //sending to the SubjectFactory.  The SubjectFactory should not need to know how to acquire sessions as the
        //process is often environment specific - better to shield the SF from these details:
        context = resolveSession(context);

        //Similarly, the SubjectFactory should not require any concept of RememberMe - translate that here first
        //if possible before handing off to the SubjectFactory:
        context = resolvePrincipals(context);

        Subject subject = doCreateSubject(context);

        //save this subject for future reference if necessary:
        //(this is needed here in case rememberMe principals were resolved and they need to be stored 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值