采用JWT令牌和Filter进行登录拦截认证

原理描述:

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 {
    @Autowired
    private Users2Service users2Service;
    @Autowired
    private 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();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //1、获取本次请求的URI
        String requestURI = request.getRequestURI();// /backend/index.html

        log.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

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值