SpringBoot使用Jwt处理跨域认证问题的教程详解

  在前后端开发时为什么需要用户认证呢?原因是由于HTTP协定是不存储状态的,这意味着当我们透过账号密码验证一个使用者时,当下一个request请求时他就把刚刚的资料忘记了。于是我们的程序就不知道谁是谁了。 所以为了保证系统的安全,就需要验证用户是否处于登陆状态。

一、JWT的组成

JWT由Header、Payload、Signature三部分组成,分别用.分隔。

下面就是一个jwt真实的样子,说白了就是一个字符串,但是里面却存储了很重要的信息。

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYXljaGVuIiwiaWQiOjIsIm5hbWUiOiJyYXkiLCJwYXNzd29yZCI6IjMyMSIsImlhdCI6MTU5MDI5OTU0OCwiZXhwIjoxNTkwMzg1OTQ4fQ.ORJNldDIfffg7D3_xu0_dBWb16y4fPLtw_r6qgScFpQ

Header:

第一部分是请求头由两部分组成,algtyp,第一个指定的是算法,第二指定的是类型。

Payload

第二部分是主体信息组成,用来存储JWT基本信息,或者是我们的信息。

Signature

第三部分主要是给第一部分跟第二部进行签名使用的,用来验证是否是我们服务器发起的Token,secret是我们的密钥。

二、在springboot项目中使用jwt做验证

具体流程:

  • 把用户的用户名和密码发到后端
  • 后端进行校验,校验成功会生成token, 把token发送给客户端
  • 客户端自己保存token, 再次请求就要在Http协议的请求头中带着token去访问服务端,和在服务端保存的token信息进行比对校验。

1.先引入jar包

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

2.使用工具类生成token和验证token(生成token方法中存入了用户的信息)

public class JwtUtils {

  //发行者
  public static final String SUBJECT="raychen";
  //过期时间 一天
  public static final long EXPIRE=1000*60*60*24;
  //密钥
  public static final String APPSECRET="raychen11";

  /**
   * 生成jwt
   * @param user
   * @return
   */
  public static String geneJsonWebToken(User user){
    if(user==null || user.getId()==null || user.getName()==null || user.getPassword()==null){
      return null;
    }
    String token=Jwts.builder().setSubject(SUBJECT)
        .claim("id",user.getId())
        .claim("name",user.getName())
        .claim("password",user.getPassword())
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis()+EXPIRE))
        .signWith(SignatureAlgorithm.HS256,APPSECRET).compact();

    return token;
  }

  /**
   * 校验token
   * @param token
   * @return
   */
  public static Claims checkJWT(String token){
    //仿造的token或者已过期就会报错
    try {
      final Claims claims=Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();
      return claims;
    }catch (Exception e){
      System.out.println("catch...");
    }
    return null;
  }
}

3.自定义注解(进行token验证)

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckToken {
  boolean required() default true;
}

4.编写config,将后台所有请求先去拦截器(拦截器返回了true,用户才可以请求到接口)

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(authenticationInterceptor())
        .addPathPatterns("/**");  // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
  }

  @Bean
  public AuthenticationInterceptor authenticationInterceptor() {
    return new AuthenticationInterceptor();
  }
}

5.定义拦截器(对需要token验证的请求,进行验证,验证成功返回true,失败返回false无法请求到接口)

public class AuthenticationInterceptor implements HandlerInterceptor {

  public static final Gson gson=new Gson();
  /**
   * 进入controller之前进行拦截
   * @param request
   * @param response
   * @param object
   * @return
   */
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
    // 如果不是映射到方法直接通过
    if (!(object instanceof HandlerMethod)) {
      return true;
    }

    HandlerMethod handlerMethod = (HandlerMethod) object;
    Method method = handlerMethod.getMethod();
    //检查是否有LoginToken注释,有则跳过认证
    if (method.isAnnotationPresent(LoginToken.class)) {
      LoginToken loginToken = method.getAnnotation(LoginToken.class);
      if (loginToken.required()) {
        return true;
      }
    }

    //前面是不需要token验证的 从 http 请求头中取出 token
    String token = request.getHeader("token");
    //检查有没有需要用户权限的注解
    if (method.isAnnotationPresent(CheckToken.class)) {
      CheckToken checkToken = method.getAnnotation(CheckToken.class);
      if (checkToken.required()) {
        if(token!=null){
          Claims claims= JwtUtils.checkJWT(token);
          if(null==claims){
            sendJsonMessage(response, JsonData.buildError("token有误"));
            return false;
          }
          Integer userId= (Integer) claims.get("id");
          String name = (String) claims.get("name");

          request.setAttribute("userId",userId);
          request.setAttribute("name",name);
          return true;
        }
        //token为null的话 返回一段json给前端
        sendJsonMessage(response, JsonData.buildError("请登录"));
        return false;
      }
    }
    //没有使用注解的方法 直接返回true
    return true;
  }

    /**
     * 响应数据给前端
     * @param response
     * @param obj
     * @throws IOException
     */
    public static void sendJsonMessage (HttpServletResponse response, Object obj) throws IOException {
      response.setContentType("application/json; charset=utf-8");
      PrintWriter writer = response.getWriter();
      writer.print(gson.toJson(obj));
      writer.close();
      response.flushBuffer();
    }
}

用户登录成功后,使用工具类生成token。token在服务端不做存储,直接将token返回给客户端,客户端下次请求服务端时,使用工具类来验证header里的token是否合法。

总结

到此这篇关于SpringBoot使用Jwt处理跨域认证问题的文章就介绍到这了,更多相关SpringBoot处理跨域认证内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-06-14

详解springboot设置cors跨域请求的两种方式

1.第一种: public class CorsFilter extends OncePerRequestFilter { static final String ORIGIN = "Origin"; protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOE

SpringBoot解决ajax跨域问题的方法

SpringBoot解决ajax跨域,供大家参考,具体内容如下 一.第一种方式 1.编写一个支持跨域请求的 Configuration import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.anno

在SpringBoot中使用JWT的实现方法

JWT简介 简介 JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记.也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据.此特性便于可伸缩性, 同时保证应用程序的安全. 在身份验证过程中, 当用户使用其凭据成功登录时, 将返回 JSON Web token, 并且必须在本地保存 (通常在本地存储中).每当用户要访问受保护的路由或资源 (端点) 时, 用户代理(user agent)必须连同请求一起发送 JWT,

vue+springboot前后端分离实现单点登录跨域问题解决方法

最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘. 刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)...,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑. 我面临的第一个问题是跨域,浏览器控制台直接报CORS,

springboot+jsonp解决前端跨域问题小结

现在咱们一起来讨论浏览器跨域请求数据的相关问题.说这样可能不是很标准,因为拒绝跨域请求数据并不是浏览器所独有的,之所以会出现跨域请求不了数据,是因为浏览器基本都实现了一个叫"同源策略"的安全规范.该规范具体是什么呢?我们在MDN上找到了一份资料,地址如下: 浏览器同源策略讲解 总的来说,当A网址和B网址在 协议 . 端口 . 域名 方面存在不同时,浏览器就会启动同源策略,拒绝A.B服务器之间进行数据请求. 说了同源策略,纸上得来终觉浅,绝知此事要躬行,到底同源策略是怎么体现的呢?下面我

详解SpringBoot多跨域请求的支持(JSONP)

在我们做项目的过程中,有可能会遇到跨域请求,所以需要我们自己组装支持跨域请求的JSONP数据,而在4.1版本以后的SpringMVC中,为我们提供了一个AbstractJsonpResponseBodyAdvice的类用来支持jsonp的数据(SpringBoot接收解析web请求是依赖于SpringMVC实现的).下面我们就看一下怎么用AbstractJsonpResponseBodyAdvice来支持跨域请求. 使用AbstractJsonpResponseBodyAdvice来支持跨域请求

解决前后端分离 vue+springboot 跨域 session+cookie失效问题

环境: 前端 vue ip地址:192.168.1.205 后端 springboot2.0 ip地址:192.168.1.217 主要开发后端. 问题: 首先登陆成功时将用户存在session中,后续请求在将用户从session中取出检查.后续请求取出的用户都为null. 解决过程: 首先发现sessionID不一致,导致每一次都是新的会话,当然不可能存在用户了.然后发现cookie浏览器不能自动保存,服务器响应set-cookie了 搜索问题,发现跨域,服务器响应的setCookie浏览器无

SpringBoot+Spring Security+JWT实现RESTful Api权限控制的方法

摘要:用spring-boot开发RESTful API非常的方便,在生产环境中,对发布的API增加授权保护是非常必要的.现在我们来看如何利用JWT技术为API增加授权保护,保证只有获得授权的用户才能够访问API. 一:开发一个简单的API 在IDEA开发工具中新建一个maven工程,添加对应的依赖如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-b

Vue+Jwt+SpringBoot+Ldap完成登录认证的示例代码

本人野生程序员一名,了解了一些微服务架构.前后端分离.SPA的知识后就想试试做点什么东西.之前一直做后端,前端只是有基础知识.之前学习过angularjs,但当时就是一脸懵逼(完全看不懂是啥)就放弃了.最近又学了Vue,这次感觉总算明白了一些,但其中也跳过很多坑(应该还会更多),在这里写下来记录一下吧. 说回主题,之前传统登录认证的方法基本是由服务器端提供一个登录页面,页面中的一个form输入username和password后POST给服务器,服务器将这些信息与DB或Ldap中的用户信息对比,

SpringBoot整合token实现登录认证的示例代码

1.pom.xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</group

SpringBoot整合Sa-Token实现登录认证的示例代码

目录 依赖 登录 退出登录 前后端分离 今天分享的是 Spring Boot 整合 Sa-Token 实现登录认证. 依赖 首先,我们需要添加依赖: 关键依赖: <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.28.0</version> </depend

SpringBoot+Mybatis实现登录注册的示例代码

学习SpringBoot+Mybatis实现的登录注册功能的Demo,实现这个Demo在网上也参考了资料和代码,本文是本人在实现Demo后的个人总结,以便理清思路. 1.环境 jdk8 : "1.8.0_281" Maven: 3.6.3 Idea:2020.2 Mysql:5.6.40 Navicat:10.1.7 2.步骤 2.1 创建一个SpringBoot项目 选择依赖如下: Web下的Spring Web. Template Engines下的Thymeleaf. SQL下的

利用Springboot实现Jwt认证的示例代码

JSON Web Token是目前最流行的跨域认证解决方案,,适合前后端分离项目通过Restful API进行数据交互时进行身份认证 关于Shiro整合JWT,可以看这里:Springboot实现Shiro+JWT认证 概述 由于概念性内容网上多的是,所以就不详细介绍了 具体可以看这里:阮一峰大佬的博客 我总结几个重点: JWT,全称Json Web Token,是一种令牌认证的方式 长相: 头部:放有签名算法和令牌类型(这个就是JWT) 载荷:你在令牌上附带的信息:比如用户的id,用户的电话号

Spring Boot 集成JWT实现前后端认证的示例代码

目录 前言 JWT简介 为什么要用JWT 传统session认证存在那些弊端? JWT认证的优势 JWT的数据结构 Header Payload Signature Spring Boot集成JWT 引入Jwt包 编写jwt工具类 Token认证拦截器 配置拦击器 登录验证流程 示例代码 总结 前言 小程序.H5应用的快速发展,使得前后端分离已经成为了趋势,然而系统认证却是系统的重要一部分,本文将讲解JWT如何实现前后端认证. JWT简介 JWT(全称:Json Web Token)是一个开放标

Vue+SpringBoot实现支付宝沙箱支付的示例代码

首先去下载支付宝沙箱的一系列东西,具体的配置什么的我就不说了,有很多博客都讲了,还有蚂蚁金服官方也说的很详细,我就直接说怎么样把后端的支付页面显示到Vue前端来: 在你配置好AlipayConfig这个文件后,就可以写前端的逻辑了,前端是采用支付宝的页面如下: 下面展示一些 内联代码片. /* 以下是支付确认html */ <div style="text=#000000 bgColor=#ffffff leftMargin=0 topMargin=4"> <head

SpringBoot创建JSP登录页面功能实例代码

添加JSP配置 1.pom.xml添加jsp解析引擎 <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.s

Vue.js中Line第三方登录api的实现代码

国际化的项目就会用用到一些第三方的登录api,这次记录一下Line 的! 按步骤来: 注册Line账号就不说了,虽然麻烦,这就自己去想办法了! demo 请狠狠的戳这里 http://download.lllomh.com/cliect/#/product/J417081951162505 一:开发者平台配置 去Line 的开发者平台 新建一个App: https://developers.line.biz/en/ ​ ​ 顺便写好资料: ​ 动态演示: ​ 这要 用到的 就是2个: Chann

Vue+Element+Springboot图片上传的实现示例

最近没事刚好联系下vue+springboot前段后分离的项目.用上了图片上传功能.记录一下. 前端待提交的表单部分代码 <el-form-item label="封面图片"> <el-upload v-model="dataForm.title" class="avatar-uploader" :limit="1" list-type="picture-card" :on-preview