您的位置:首页 > 财经 > 产业 > b2b电子商务平台开发商_网页设计培训班招生_北京网站seo哪家公司好_网站推广的100种方法

b2b电子商务平台开发商_网页设计培训班招生_北京网站seo哪家公司好_网站推广的100种方法

2024/12/23 11:55:20 来源:https://blog.csdn.net/wrjwww/article/details/144294598  浏览:    关键词:b2b电子商务平台开发商_网页设计培训班招生_北京网站seo哪家公司好_网站推广的100种方法
b2b电子商务平台开发商_网页设计培训班招生_北京网站seo哪家公司好_网站推广的100种方法

登录校验

  • 1、JWT令牌技术
    • 1.1 JWT令牌介绍
    • 1.2 Java代码生成与校验JWT令牌
  • 2、Filter过滤器
    • 2.1 Filter过滤器的简单实现
    • 2.2 配置拦截路径
    • 2.3 Filter接口中的三个方法:
    • 2.4 Filter过滤器登录校验
    • 2.5 过滤器链
  • 3、Interceptor拦截器
    • 3.1 拦截器(Interceptor)的简单实现
    • 3.2 配置拦截路径
    • 3.3 拦截器中的三个方法
    • 2.4 Interceptor拦截器登录校验

登录校验是系统开发中不可缺少的一环。

1、JWT令牌技术

1.1 JWT令牌介绍

JWT全称为 JSON Web Token(https://jwt.io/)。JWT定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。
JWT令牌由三部分组成:

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

Header和Payload会通过Base64编码生成。Signature部分会通过Header指定的签名算法,以Header、Payload以及指定的秘钥作为签名算法输入计算得到。这三部分共同组成了JWT令牌。

1.2 Java代码生成与校验JWT令牌

Java代码生成与校验令牌需要引入JWT的相关依赖:

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

生成JWT令牌需要准备四个数据:签名算法、秘钥、有效时间和载荷(自定义内容)
签名算法有很多种,可以在JWT官网查看。
下面通过一个简单的例子感受一下:
生成JWT令牌:

@Test
public void testJWT(){// 准备Map集合载荷Map<String, Object> claims = new HashMap<>();claims.put("id", 1);claims.put("name", "Tom");String jwt = Jwts.builder() // 使用Jwts中的builder()方法构造.signWith(SignatureAlgorithm.HS256, "wrj-web") // 指定签名算法和秘钥.setClaims(claims) // 加入载荷.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) // 设置有效时间:当前时间 + 有效时长,单位为ms.compact();System.out.println(jwt);
}
// 运行输出:
// eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTczMzU0MTk2MX0.AgNXthmTMBJHKIeSaacBf-wThVNwsPi1F63sAqsuJkY

解析JWT令牌:

    @Test void testParseJWT(){Claims claims = Jwts.parser() // 使用Jwts中的parser()方法开始解析.setSigningKey("wrj-wrb") // 指定秘钥.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTczMzU0MTk2MX0.AgNXthmTMBJHKIeSaacBf-wThVNwsPi1F63sAqsuJkY") // 输入JWT令牌,此处直接输入上述代码生成的JWT令牌.getBody(); // 获取载荷System.out.println(claims);}
// 运行输出:
// {name=Tom, id=1, exp=1733541961}

通常会将JWT生成与解析的代码封装成JWT工具类来使用,JwtUtil工具类中只有两个成员方法,一个用于生成JWT令牌,一个用于解析JWT令牌:

public class JwtUtil {/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥** @param secretKey jwt秘钥* @param ttlMillis jwt过期时间(毫秒)* @param claims    设置的信息* @return*/public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 生成JWT有效时间long expMillis = System.currentTimeMillis() + ttlMillis;Date exp = new Date(expMillis);// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(exp);return builder.compact();}/*** Token解密** @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param token     加密后的token* @return*/public static Claims parseJWT(String secretKey, String token) {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;}
}

对于一般项目而言,JWT令牌需要的签名秘钥、有效时长以及前端传递过来的令牌名称是较为固定的,可以在配置到配置文件中,以便修改。
步骤如下:

  1. 在配置文件中自定义配置参数,代码如下:
web:jwt:# 设置jwt签名加密时使用的秘钥secret-key: itcast# 设置jwt过期时间 单位msttl: 7200000# 设置前端传递过来的令牌名称token-name: token
  1. 定义一个properties类用于接收配置信息,类名一般为JwtProperties,注意成员变量名与配置信息中设置的名称要对应。
@Component // 注册成Bean
@ConfigurationProperties(prefix = "web.jwt") // 关联到配置文件中web->jwt下的配置信息
@Data // Lombok注解,生成get/set等方法
public class JwtProperties {// 签名秘钥,与配置文件中secret-key对应private String secretKey;// jwt过期时间,与配置文件中ttl对应private long ttl;// 前端传递过来的令牌名称,与配置文件中token-name对应private String tokenName;
}

在需要使用这些信息时,只需要将JwtProperties 对象注入,然后通过get/set方法获取即可。

2、Filter过滤器

过滤器能够把对资源的请求拦截下来,从而实现一些特殊的功能,例如登录校验、敏感字符处理等。
在这里插入图片描述

2.1 Filter过滤器的简单实现

Filter过滤器使用分两步:

  1. 定义Filter:定义一个类,实现Filter接口,并重写其所有方法。Filter接口是javax.servlet.*包下的Filter接口。
  2. 配置Filter:Filter类上加@WebFilter注解,配置拦截资源路径。引导类(启动类)上加@ServletComponentScan开启Servlet组件支持。
@WebFilter(urlPatterns = "/*") // 通过WebFilter注解表示这是一个web过滤器组件,通过urlPatterns属性配置拦截路径
public class DemoFilter implements Filter {// 初始化方法、Web服务器启动,创建Filter时调用,只调用一次。通常在此方法中完成资源和环境的准备操作@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}// 每次拦截到请求时会调用@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("拦截请求...放行前逻辑");filterChain.doFilter(servletRequest, servletResponse);System.out.println("拦截请求...放行后逻辑");}// 销毁方法,Web服务器关闭时调用,只调用一次。通常完成资源的释放等操作@Overridepublic void destroy() {Filter.super.destroy();}
}

2.2 配置拦截路径

Filter过滤器的拦截路径通过 @WebFilter 注解中的 urlPatterns 属性设置,有三种方式:

拦截路径urlPatterns含义
拦截具体路径/login只有访问 /login 路径时,才会被拦截
目录拦截/emps/*访问 /emps 下的所有资源,都会被拦截
拦截所有/*访问所有资源,都会被拦截

2.3 Filter接口中的三个方法:

Filter接口中的三个方法有各自的执行时机和作用。

  • init():初始化方法、Web服务器启动,创建Filter时调用,只调用一次。通常在此方法中完成资源和环境的准备操作;
  • doFilter():每次拦截到请求时会调用。其中可包含放行前逻辑和放行后逻辑;
  • destroy():销毁方法,Web服务器关闭时调用,只调用一次。通常完成资源的释放等操作

在使用Filter过滤器时需要注意几点:

  1. 执行doFilter()方法时首先执行其中的放行前逻辑,然后放行。
  2. 过滤器放行,访问完对应路径的资源之后会回到过滤器。
  3. 回到过滤器之后还会执行放行后逻辑。

2.4 Filter过滤器登录校验

下面改造doFilter()方法,实现登录校验功能。
场景:用户进行登录操作不进行拦截,其他操作进行拦截。也就是不拦截"/login"路径,拦截其他所有路径。
拦截逻辑分为以下几步:
1.获取请求路径;
2.判断路径中是否包含"login",包含则直接放行,不包含则需拦截,进行登录校验;Filter放行是通过执行filterChain调用doFilter()方法
3.进行登录校验,首先获取JWT令牌;
4.判断JWT令牌是否存在,或是否为空。不存在或为空则校验失败,不放行,直接return结束。
5.解析JWT令牌,不成功则不放行;
6.解析JWT令牌成功则放行。

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;// 1.获取请求的URLString url = req.getRequestURL().toString();// 2.判断login是否存在,存在则放行,不存在则拦截if(url.contains("login")) {filterChain.doFilter(servletRequest, servletResponse);return;}// 3.获取JWT令牌String jwt = req.getHeader("token");// 4.判断JWT是否存在if(!StringUtils.hasLength(jwt)) {Result error = Result.error("NOT_LOGIN");String s = JSONObject.toJSONString(error);resp.getWriter().write(s);return;}// 5.判断JWT是否能解析成功try {JwtUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();Result error = Result.error("NOT_LOGIN");String s = JSONObject.toJSONString(error);resp.getWriter().write(s);return;}// 6.解析成功,放行filterChain.doFilter(servletRequest, servletResponse);}

这部分登录校验的代码是可以进行优化的。因为实际业务中是不会对 /login 登录请求进行拦截的。

2.5 过滤器链

一个Web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链。
由于存在多个过滤器,过滤器的执行顺序会按照过滤器类名(字符串)的自然顺序

3、Interceptor拦截器

拦截器是一种动态拦截方法调用的机制,类似与过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。拦截器通常用来拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。

3.1 拦截器(Interceptor)的简单实现

Interceptor拦截器的使用分两步:

  1. 定义拦截器:实现HandlerInterceptor接口,并重写其所有方法,在实现类上加上@Component注解,交给IOC容器管理;
@Component // 注册成Bean,交给IOC容器管理
public class DemoInterceptor implements HandlerInterceptor {// 目标资源方法执行前执行,返回true:放行,返回false:不放行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...");return true;}// 目标资源方法执行后执行@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");}// 视图渲染完毕后执行,最后执行@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion...");}
}
  1. 注册配置拦截器。创建一个配置类,实现WebMvcConfigurer接口。在配置类上加@Configuration注解,代表当前类是配置类。重写WebMvcConfigurer接口的addInterceptors方法,使用该方法的形参registry调用addInterceptor方法,将创建好的拦截器注册进去。因此需要先将拦截器注入。然后接着调用addPathPatterns()和excludePathPatterns()方法配置拦截哪些路径,不拦截哪些路径。
@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate DemoInterceptor demoInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(demoInterceptor) // 注册拦截器.addPathPatterns("/**") // 配置拦截资源.excludePathPatterns("/login"); // 配置不拦截的资源               }
}

3.2 配置拦截路径

Interceptor拦截器的拦截路径是在配置类中进行配置的。可借鉴上述配置类的代码。
下面介绍Interceptor的拦截路径:

拦截路径含义举例
/*一级路径能匹配 /depts、/emps、/login,不能匹配 /depts/1
/**任意级路径能匹配 /depts、/depts/1、/depts/1/2
/depts/*/depts下的一级路径能匹配 /depts/1、不能匹配 /depts/1/2,/depts
/depts/**/depts下的任意级路径能匹配 /depts、/depts/1、/depts/1/2、不能匹配 /emps/1

3.3 拦截器中的三个方法

Interceptor接口中的三个方法有各自的执行时机和作用。

  • preHandle():目标资源方法执行前执行,返回true:放行,返回false:不放行;
  • postHandle():目标资源方法执行后执行;
  • afterCompletion():视图渲染完毕后执行,最后执行。

2.4 Interceptor拦截器登录校验

Interceptor拦截器进行登录校验与Filter过滤器实现登录校验的逻辑相同,只是部分实现细节不同。这里提供一个简单的实现。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1. 获取请求路径String url = request.getRequestURL().toString();// 2. 判断请求路径是否包含 /loginif(url.contains("login")) {return true;}// 3. 从请求头获取token,一般把JWT令牌的key名设置为tokenString jwt = request.getHeader("token");// 4. 判断是否获取到JWT令牌if(!StringUtils.hasLength(jwt)) {Result error = Result.error("NOT_LOGIN");String s = JSONObject.toJSONString(error);response.getWriter().write(s);return false;}// 5. 解析JWT令牌try {JwtUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();Result error = Result.error("NOT_LOGIN");String s = JSONObject.toJSONString(error);response.getWriter().write(s);return false;}return true;}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com