SpringBoot学习(黑马程序员day12)

1jwt令牌

JWT的组成: (JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)
第一部分:Header(头), 记录令牌类型、签名算法等。 例如:
{"alg":"HS256","type":"JWT"}
第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:
{"id":"1","username":"Tom"}
第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加
入指定秘钥,通过指定签名算法计算而来。

1.1jwt令牌的生成:

1.1.1添加依赖:

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
@Test
public void genJwt(){
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","Tom");
String jwt = Jwts.builder()
 .setClaims(claims) //自定义内容(载荷) 
 .signWith(SignatureAlgorithm.HS256, "itheima") //签名算法
 .setExpiration(new Date(System.currentTimeMillis() +
24*3600*1000)) //有效期
 .compact();
System.out.println(jwt);
}

1.2jwt令牌的校验:

 @Test
    public void parseJwt() {
        Claims claims = Jwts.parser()
                .setSigningKey("itheima")//指定签名密钥(必须保证和生成令牌时使用  相同的签名密钥)
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiamlueW9uZyIsImlkIjoxLCJleHAiOjE2OTk1MTU4MzV9.fE2BfR6WlmlnrFdCeHsvfTMKdo623Sg5FDf3Ql5mi9Q")
                .getBody();
        System.out.println(claims);
    }
JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。
如果JWT令牌解析校验时报错,则说明 JWT令牌被篡改 或 失效了,令牌非法。

1.3服务端响应客户端jwt令牌:

1.3.1 生成jwt的工具类:

public class JwtUtil {
    private static String signKey = "itheima";//签名密钥
    private static Long expire = 43200000L; //有效时间

    public static String generateJwt(Map<String, Object> claims) {
        String jwt = Jwts.builder()
                .addClaims(claims)//自定义信息(有效载荷)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() +
                        expire))//过期时间
                .compact();
        return jwt;
    }
    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)//指定签名密钥
                .parseClaimsJws(jwt)//指定令牌Token
                .getBody();
        return claims;
    }
}

1.3.2在登录控制类中实现:

public Result loginByName(@RequestBody Emp emp) {
        log.info("用户登录功能");
        Emp emp1 = loginService.loginByName(emp);
        if (emp1 != null) {

            Map<String, Object> stringObjectMap = new HashMap<>();
            stringObjectMap.put("id", 1);
            stringObjectMap.put("name", "jinyong");
            String jwt = JwtUtil.generateJwt(stringObjectMap);
           return Result.success(jwt);
        } else {
            return Result.success("登录失败");
        }
    }

2 过滤器Filter

2.1实现步骤:

1步,定义过滤器 :1.定义一个类,实现 Filter 接口,并重写其所有方法。
第2步,配置过滤器:Filter类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加
@ServletComponentScan 开启Servlet组件支持。

实现类:

package com.heima.Filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import org.springframework.context.annotation.ComponentScan;

import java.io.IOException;

@WebFilter(urlPatterns = "/*")
public class Filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        System.out.println("生成了一个过滤器");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器放行");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
        System.out.println("销毁了过滤器");
    }
}

2.2过滤器的拦截路径:

SpringBoot学习(黑马程序员day12)_第1张图片
设置方式,例如:@WebFilter(urlPatterns = "/*")

2.3实现登录的拦截:


@Slf4j
@WebFilter(urlPatterns = "/*") //拦截所有请求
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse, FilterChain chain) throws
            IOException, ServletException {
//前置:强制转换为http协议的请求对象、响应对象 (转换原因:要使用子类中特有方法)
        HttpServletRequest request = (HttpServletRequest)
                servletRequest;
        HttpServletResponse response = (HttpServletResponse)
                servletResponse;
//1.获取请求url
        String url = request.getRequestURL().toString();
        log.info("请求路径:{}", url);
        if(url.contains("/login")){
            chain.doFilter(request, response);//放行请求
            return;//结束当前方法的执行
        }
//3.获取请求头中的令牌(token)
        String token = request.getHeader("token");
        log.info("从请求头中获取的令牌:{}",token);
//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(token)){
            log.info("Token不存在");
            Result responseResult = Result.error("NOT_LOGIN");
              //没有Restrequest注解不能自动转为json格式的数据
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);
            return;
        }
//5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtil.parseJWT(token);
        }catch (Exception e){
            log.info("令牌解析失败!");
            Result responseResult = Result.error("NOT_LOGIN");
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            response.setContentType("application/json;charset=utf-8");
//响应
            response.getWriter().write(json);
            return;
        }
//6.放行
        chain.doFilter(request, response);
    }
}

需要导入aliyun的json依赖:

 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

你可能感兴趣的:(spring,boot,学习,java)