Shiro实现jwt验证流程梳理

Shiro实现jwt验证流程梳理

Shiro jwt实现
jwt验证原理

由于业务需要用到jwt验证,需要把实现的用户密码验证方式修改为jwt的验证方式.
在把之前的登录流程修改为jwt验证时,是省略掉了shiro内部的login步骤和session管理
代码修改如下:

-        Subject subject = SecurityUtils.getSubject();
-        subject.login(usernamePasswordToken); //完成登录
-        UserInfo2 user = (UserInfo2) subject.getPrincipal();
-        session.setAttribute(Constant.CURRENT_USER, user);
+        if (userBean.getPasswrod().equals(loginInfo.getPassword())) {
+            String token = JWTUtil.sign(loginInfo.getLoginname(),loginInfo.getPassword());
+            SessionManager.addOrUpdateSessionEntity(token,SessionManager.USER_BEAN,userBean);
+            return new Result<String >(200,"success", token);
+        }

由于在controller省略掉了登录流程,需要添加Filter过滤,在Filter中调用login步骤,代码执行流程:
preHandle->isAccessAllowed->isLoginAttempt->executeLogin

login的登录调用流程如下

 executeLogin
    login
      authenticate
        onAuthenticate
          UserRealm::getAuthenticationInfo
            doGetAuthenticationInfo

真正的验证流程还是在UserRealm::doGetAuthenticationInfo

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        String token = (String) auth.getCredentials();
        // 解密获得username,用于和数据库进行对比
        String loginname = JWTUtil.getLoginname(token);
        if (loginname == null) {
            throw new AuthenticationException("token can not match !");
        }
        UserBean userBean = (UserBean) SessionManager.getSessionEntity(token,SessionManager.USER_BEAN);

        if (userBean == null ) {
            userBean = userService.getUserBean(loginname);
            if (userBean == null) {
                throw new AuthenticationException("user " + loginname + " does not exist");
            } else {
                SessionManager.addOrUpdateSessionEntity(token,SessionManager.USER_BEAN,userBean);
            }

        }
        if (! JWTUtil.verify(token, loginname, userBean.getPasswrod())) {
                throw new AuthenticationException("username or password is wrong");
        }
        return new SimpleAuthenticationInfo(token, token, "userRealm");
    }
  1. 为什么需要在Filter中调用login,不能在loginUser中调用login?
    由于Shiro默认的验证方式是基于session的,在基于token验证的方式中,不能依赖session做为登录的判断依据.
    Shiro预定义的AuthenticationFilter::isAccessAllowed
 protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        Subject subject = getSubject(request, response);
        return subject.isAuthenticated();
    }

在JWTFilter中,如下

    @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
       try {
           if (!isLoginAttempt(request, response) || !executeLogin(request,response)) {
               response401(request,response);
           }
       } catch (UnauthorizedException e) {
           response403(request,response);
           return false;
       } catch (AuthenticationException ae) {
           response401(request, response);
           return false;
       }

        return true;
    }

其中isLoginAttempt时通过判断请求的httpHeader中是否包含Authentication字段,在这里,自定义的字段取值为jwt token.

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值