springboot shiro jwt demo实战项目

…衆ロ難τιáo~ 提交于 2020-01-20 12:16:46

简介

  • shiro 是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。
  • jwt JSON Web Token 是目前最流行的跨域认证解决方案,无状态会话。

项目乔迁

shiro处理无状态校验上存在session保留问题,已改为用java脑洞 springboot 轻量级JWT安全框架

Git地址

https://gitee.com/wqrzsy/lp-demo/tree/master/lp-shiro-jwt

更多demo请关注

springboot demo实战项目
java 脑洞
java 面试宝典
开源工具

项目分析

####1. 自定义权限注解,支持基于注解和配置表多种方式配置过滤规则
QQ截图20190428154402.png

注解的使用方式
QQ截图20190428154424.png

配置表方式
QQ截图20190428154442.png

最后的结果
QQ截图20190428154600.png

注意:这里的顺序是配置表的配置会覆盖注解的

####2. 封装校验核心逻辑,抽离业务接口
image.png

####3. InitBean 初始化对象
image.png

####4. jwt刷新 使用过滤器TokenRefreshFilter
判断header是否有token,如果有则判断是否到了刷新时间,如果是则刷新token重新放入到header中

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletResponse.setCharacterEncoding("utf-8");
        Object token = servletRequest.getAttribute(AccountAide.JWT_TOKEN_NAME);
        if (token != null) {
            refreshJwtToken(WebUtils.toHttp(servletRequest), WebUtils.toHttp(servletResponse), token.toString());
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    protected void refreshJwtToken(HttpServletRequest request, HttpServletResponse response, String jwtToken) {
        try {
            //ZoneId.systemDefault() 时区
            //签发时间
            LocalDateTime issueTime = LocalDateTime.ofInstant(JwtUtils.getIssuedAt(jwtToken).toInstant(), ZoneId.systemDefault());
            if (this.getRefreshTime(issueTime).isBefore(LocalDateTime.now())) {
                Long uid = JwtUtils.getUid(jwtToken);
                AccountInfo accountInfo = accountInfoService.getAccountInfo(uid);
                AccountAide.bindJwtToken(accountInfo, request, response, shiroConfig.getTokenExpireTime());
            }
        } catch (Exception e) {
            LOGGER.error("刷新JWT令牌异常: ", e);
        }
    }

####5. 禁用session
因为jwt无需session支持,所以要把默认session支持关掉

  1. SessionStorageEvaluator
    /**
     * JWT 下禁用session, 不保存用户登录状态。保证每次请求都重新认证。
     * 需要注意的是,如果用户代码里调用Subject.getSession()还是可以用session,如果要完全禁用,要配合下面的noSessionCreation的Filter来实现
     */
    protected SessionStorageEvaluator createSessionStorageEvaluator() {
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }
  1. NoSessionCreationFilter
    其实NoSessionCreationFilter中只有一行代码,就是在进入shiroFilter之前把SESSION_CREATION_ENABLED这个属性设为false
public class NoSessionCreationFilter extends PathMatchingFilter {

    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        request.setAttribute(DefaultSubjectContext.SESSION_CREATION_ENABLED, Boolean.FALSE);
        return true;
    }
}

所以我们结合一下,直接把NoSessionCreationFilter 和我们的JwtAuthFilter结合一起

public class JwtAuthFilter extends AuthenticatingFilter {

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

    /**
     * 合并 noSessionCreation Filter
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     * @throws Exception
     */
    @Override
    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        request.setAttribute(DefaultSubjectContext.SESSION_CREATION_ENABLED, Boolean.FALSE);
        return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
    }

}

####6. 配置表

shiro:
  login:
    token:
      expireTime: 300000
    password:
      expireTime: 300000
  filterChains:
logging:
  config: classpath:logback-boot.xml

7. 测试

http://localhost:8080/swagger-ui.html

demo项目导入

参考: https://www.jianshu.com/p/cd0275a2f5fb
注意:该DEMO可以作为子项目直接集成在项目中

公众号

五分钟了解前沿技术,大数据,微服务,区域链,提供java前沿技术干货,独立游戏制作技术分享

五分钟技术

如果这篇文章对你有帮助请给个star
image.png

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!