原理描述:
1、第一次登录的时候,生成JWT令牌,并JWT令牌存放在localStorage。
localStorage.setItem('token', token);
2、每次通过axios发送请求的时候,都将这个令牌获取,并放于header中发送。
也就是JWT令牌只在登录的时候,有服务器发过来客户端,并保存在客户端。后面客户通过浏览器进行的每次请求,都需要带上这个保存有jwt令牌的header
(1)从客户端获取token:
token: localStorage.getItem("token") || ""
(2)axios发送的时候,携带token
axios.get(url, {headers: {'token': this.token // 注意:这里的'token'应该与后端期望的请求头名称一致} })
3、服务端获取token,并进行判断。
String token = request.getHeader("token");
详细的代码如下:
1、login.html登录页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>传参数(实体)</title><!-- 引入组件库 --><script src="js/jquery.min.js"></script><script src="js/vue.js"></script><script src="js/element.js"></script><script src="js/axios-0.18.0.js"></script><link rel="stylesheet" href="js/element.css"></head>
<body><div id="app"><el-form ref="form" :model="form" label-width="80px"><el-form-item label="姓名"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="密码"><el-input v-model="form.password"></el-input></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">提交</el-button><el-button>取消</el-button></el-form-item></el-form>
</div>
<script>new Vue({el:"#app",data:{form: {name: '',password: ''},tableData: []},methods:{onSubmit() {var url = `/loginJwt`axios.post(url, {name: this.form.name,password: this.form.password}).then(response => {this.tableData = response.data;const token = response.data.data;localStorage.setItem('token', token);if(this.tableData.data!=null) {location.href = 'poemList.html'}else {location.href = 'error.html'}}).catch(error=>{console.error(error);alert('登录失败,请检查您的用户名和密码');})}}})</script></body>
</html>
2、poemList.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>显示所有(删除用按钮和链接均实现)</title><script src="./js/vue.js"></script><script src="./js/axios-0.18.0.js"></script></head>
<body>
<h1 align="center">诗人信息列表listAll</h1>
<div id="app" align="center"><a href="peot_insert.html">新增</a><table border="1"><tr><th>id</th><th>author</th><th>gender</th><th>dynasty</th><th>title</th><th>style</th><th>操作</th></tr><tr v-for="peot in poemList"><td>{{peot.id}}</td><td>{{peot.author}}</td><td>{{peot.gender}}</td><td>{{peot.dynasty}}</td><td>{{peot.title}}</td><td>{{peot.style}}</td><td><!--<button type="button" @click="deleteId(peot.id)">删除</button>--><button type="button" @click="deleteId_restful(peot.id)">删除</button><a :href="'peot_delete2.html?id='+peot.id">删除</a><a :href="'peot_edit.html?id='+peot.id">修改</a></td></tr></table>
</div></body><script>new Vue({el: "#app",data: {poemList: [],token: localStorage.getItem("token") || ""},methods: {findAll() {var url = `/poem_index1`axios.get(url, {headers: {'token': this.token }}).then(response => {this.poemList = response.data.data; }).catch(error => {console.log(error);});}},created() {this.findAll(); // 组件创建时发送请求}});
</script></html>
3、controller
package com.example.controller;import com.example.pojo.Peot;
import com.example.pojo.Result;
import com.example.pojo.Users;
import com.example.service.PeotService;
import com.example.service.Users2Service;
import com.example.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;//在springboot项目中,使用jwt令牌技术进行登录验证。@RestController
@Slf4j
public class LoginJwtController {@Autowiredprivate Users2Service users2Service;@Autowiredprivate PeotService peotService;@PostMapping("/loginJwt")public Result login(@RequestBody Users users) {//调用业务层:登录功能Users loginUser = users2Service.login(users);//判断:登录用户是否存在if(loginUser !=null ){//自定义信息Map<String , Object> claims = new HashMap<>();claims.put("id", 123);claims.put("password",loginUser.getPassword());claims.put("name",loginUser.getName());//使用JWT工具类,生成身份令牌String token = JwtUtils.generateJwt(claims);System.out.println(token);Map<String, String> response = new HashMap<>();response.put("token", token);return Result.success(token);}return Result.error("用户名或密码错误");}@GetMapping("/poem_index1")public Result index1() {List<Peot> peotList =peotService.findAll();return Result.success(peotList);}}
4、过滤器LoginCheck2Filter
package com.example.filter;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.pojo.Result;
import com.example.utils.JwtUtils;import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 检查用户是否已经完成登录*/
@WebFilter(filterName = "loginCheck2Filter",urlPatterns = "/*")
@Slf4j
public class LoginCheck2Filter implements Filter{//路径匹配器,支持通配符public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//1、获取本次请求的URIString requestURI = request.getRequestURI();// /backend/index.htmllog.info("拦截到请求:{}",requestURI);//定义不需要处理的请求路径String[] urls = new String[]{"/loginJwt","/logout","/login/**"};//2、判断本次请求是否需要处理boolean check = check(urls, requestURI);//3、如果不需要处理,则直接放行if(check){log.info("本次请求{}不需要处理",requestURI);filterChain.doFilter(request,response);return;}//3.获取请求头中的令牌(token)String token = request.getHeader("token");log.info("从请求头中获取的令牌:{}",token);if(!StringUtils.hasLength(token)){log.info("Token不存在");Result responseResult = Result.error("Token不存在");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);response.setContentType("application/json;charset=utf8");//响应response.getWriter().write(json);return;}//5.解析token,如果解析失败,返回错误结果(未登录)try {JwtUtils.parseJWT(token);}catch (Exception e){log.info("令牌解析失败!");Result responseResult = Result.error("令牌解析失败!");//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)String json = JSONObject.toJSONString(responseResult);response.setContentType("application/json;charset=utf8");//响应response.getWriter().write(json);return;}//6.放行filterChain.doFilter(request, response);}/*** 路径匹配,检查本次请求是否需要放行* @param urls* @param requestURI* @return*/public boolean check(String[] urls,String requestURI){for (String url : urls) {boolean match = PATH_MATCHER.match(url, requestURI);if(match){return true;}}return false;}
}
5、启动类
一定要加上@ServletComponentScan