SpringWeb后端开发-登录认证

news2024/9/23 13:22:34

Author:Dawn_T17🥥 

目录

登录功能 

基础登录

登录校验

一、会话技术

1.基于 Cookie 和 Session 的传统会话技术(传统)

2.基于 Token 的会话技术(如 JWT)(主流)​

JWT

二、过滤器(Filter)

具体代码展现 

三、拦截器(Interceptor)


在 Spring Web 后端开发中,登录认证是确保系统安全性的重要环节。以下是关于 Spring Web 后端开发中登录认证的介绍:

一、为什么需要登录认证

  1. 保护系统资源

    • 防止未经授权的用户访问敏感信息和功能。只有通过合法认证的用户才能访问特定的页面、数据或执行特定的操作。
    • 确保系统数据的保密性、完整性和可用性。
  2. 确保用户身份真实性

    • 验证用户的身份,确保与系统交互的是合法的用户,而不是恶意攻击者或冒充者。
    • 为用户提供个性化的服务和体验,根据用户的身份和权限展示不同的内容和功能。

二、常见的登录认证方式

  1. 基于用户名和密码的认证

    • 这是最常见的认证方式。用户在登录页面输入用户名和密码,后端系统对其进行验证。
    • 通常会对密码进行加密存储,以防止密码泄露。在验证时,将用户输入的密码加密后与存储的密码进行比较。
    • 可以结合盐值(salt)来增加密码的安全性,防止彩虹表攻击。
  2. 基于令牌(Token)的认证

    • 当用户成功登录后,后端系统生成一个令牌并返回给客户端。客户端在后续的请求中携带这个令牌,后端系统通过验证令牌来确定用户的身份。
    • 令牌可以是 JWT(JSON Web Token)等格式,具有自包含性和可验证性。
    • 令牌可以设置有效期,过期后需要用户重新登录获取新的令牌。
  3. 单点登录(SSO)

    • 允许用户在一个系统中登录后,无需在其他相关系统中再次登录。通过共享用户认证信息,实现一次登录,多处访问。
    • 常见的实现方式有 CAS(Central Authentication Service)等。

三、Spring Security 实现登录认证

Spring Security 是一个强大的安全框架,用于在 Spring 应用中实现安全功能,包括登录认证。

  1. 配置用户存储

    • 可以使用内存存储、数据库存储或 LDAP 等方式存储用户信息。
    • 定义用户的用户名、密码、角色等信息。
  2. 配置认证方式

    • 选择合适的认证方式,如基于表单的认证、基于 HTTP Basic 认证等。
    • 配置登录页面、登录处理 URL、错误页面等。
  3. 配置授权规则

    • 根据用户的角色或权限,配置不同的访问规则。
    • 可以限制某些 URL 只能被特定角色的用户访问。
  4. 集成其他安全功能

    • 可以与其他安全技术集成,如加密、数字签名、OAuth2 等。

四、登录认证的流程

  1. 用户提交登录请求

    • 用户在客户端输入用户名和密码,然后将登录请求发送到后端服务器。
  2. 后端验证用户信息

    • 后端系统接收到登录请求后,根据配置的用户存储和认证方式,验证用户的用户名和密码是否正确。
    • 如果验证通过,生成令牌或设置会话信息,标识用户已登录。
  3. 返回认证结果

    • 如果登录成功,后端系统返回相应的认证结果,如令牌、会话 ID 等。客户端可以将这些信息存储在本地,以便在后续的请求中使用。
    • 如果登录失败,返回错误信息,提示用户重新输入用户名和密码。
  4. 后续请求的认证

    • 在用户登录成功后,客户端在后续的请求中携带令牌或会话信息。
    • 后端系统接收到请求后,验证令牌或会话信息的有效性,确定用户的身份和权限。
    • 根据用户的权限,允许或拒绝用户对特定资源的访问。

总之,在 Spring Web 后端开发中,登录认证是确保系统安全的重要环节。通过选择合适的认证方式,结合 Spring Security 等安全框架,可以实现高效、安全的登录认证功能。

登录功能 

基础登录

基础分析

只要根据用户名和密码查询数据库,查询出结果不为空,即为登录成功 。

基本设计流程

因为用户名和密码每个Emp(员工)都有,所以不用创建新的对象存数据,直接用Emp存 传入进来的用户名和密码数据

但是因为请求路径不同,所以Controller要重写

Controller

package com.traingcase.controller;


import com.traingcase.pojo.Emp;
import com.traingcase.pojo.Result;
import com.traingcase.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    //因为用户名和密码每个Emp(员工)都有
    // 所以不用创建新的对象存数据,直接用Emp存
    public Result login(@RequestBody Emp emp){
        log.info("员工登录:{}",emp);
        Emp e=empService.login(emp);
        return e != null? Result.success():Result.error("用户名或密码错误");
    }
}

Service

 @Override
    public Emp login(Emp emp) {
        Emp e=empMapper.getByUsernameAndPassword(emp);
        return e;
    }

Mapper

 /**
     * 根据用户名和密码查询员工
     * @param emp
     * @return
     */
    @Select("select * from emp where username=#{username} and password= #{password}")
    Emp getByUsernameAndPassword(Emp emp);

ApiPost测试 

登录校验

经过前后端联调测试 发现Bug ——>退出登录,关闭网页,重新加载网页,直接进入系统,不用登录。 

原因:目前设置的每个请求路径都是独立的,登录操作只是空有其表

                因为前后端交互基于HTTP协议,而HTTP协议是无状态的。

解决方法

会话技术

会话技术是在 Web 应用中用于跟踪用户状态和维持用户与服务器之间交互的技术手段。

在 Web 应用中,由于 HTTP 协议是无状态的,即服务器无法区分不同的请求是否来自同一个用户。为了解决这个问题,会话技术应运而生。

会话技术的作用

  1. 跟踪用户状态

    • 通过会话技术,服务器可以识别不同请求来自同一个用户,并记录用户的状态信息,如登录状态、购物车内容、浏览历史等。
    • 这样,用户在不同页面之间切换时,服务器能够根据会话信息为用户提供个性化的服务和体验。
  2. 维持用户与服务器之间的交互

    • 会话技术使得用户与服务器之间的交互可以跨越多个请求。例如,用户在一个页面上提交表单,服务器处理后返回结果,用户可以在另一个页面上继续操作,而服务器能够根据会话信息保持对用户操作的连贯性。

目前主流的会话技术主要有以下几种:

1.基于 Cookie Session 的传统会话技术(传统)

  1. 工作原理

    • 当用户首次访问服务器时,服务器为该用户创建一个唯一的 Session ID,并通过在响应中设置 Cookie 的方式将 Session ID 返回给客户端。客户端在后续的请求中会自动携带这个 Cookie,服务器根据 Cookie 中的 Session ID 找到对应的 Session 对象,从而获取用户的状态信息。
    • Session 对象通常存储在服务器的内存中,可以存储用户的登录状态、购物车信息等各种数据。
  2. 优点

    • 相对简单易用,被广泛支持。许多编程语言和 Web 框架都提供了对 Session 的内置支持。
    • 安全性较高,因为 Session 数据存储在服务器端,不容易被客户端篡改。
  3. 缺点

    • 服务器资源消耗较大,尤其是在高并发场景下,大量的 Session 对象会占用服务器的内存。
    • 如果服务器集群部署,需要进行 Session 共享,增加了系统的复杂性。

Cookie 

纠正:3->请求头非请求体

 设置Cookie和获取Cookie的代码展示

以及请求响应过程中传递Cookie的过程展示

优缺点: 

跨域:跨域在 Web 开发中是指当一个网页的脚本试图访问来自不同源(不同的域名、协议或端口)的资源时的情况。 

Sesssion

2.基于 Token 的会话技术(如 JWT)(主流)

  1. 工作原理

    • 用户在登录成功后,服务器根据用户信息生成一个包含用户身份和权限等信息的 Token(令牌),并将其返回给客户端。客户端在后续的请求中携带这个 Token服务器通过验证 Token 的有效性来确定用户的身份和状态。
    • Token 通常是一个经过加密的字符串,可以使用对称加密或非对称加密算法进行签名,以确保其真实性和完整性。
  2. 优点

    • 无状态,服务器不需要存储会话信息,减轻了服务器的负担,易于水平扩展。
    • 可以在不同的服务器之间共享,适用于分布式系统和微服务架构。
    • 具有较好的跨平台性,可以在不同的客户端(如 Web 浏览器、移动应用等)中使用。
  3. 缺点

    • 一旦 Token 被泄露,可能会导致安全问题,因为 Token 中包含了用户的敏感信息。
    • Token 的有效期管理相对复杂,如果 Token 过期时间设置过长,可能会增加安全风险;如果设置过短,可能会影响用户体验。
JWT

JWT(JSON Web Token)是一种用于在网络应用环境中进行安全信息传递的开放标准。

Jwt令牌生成

/**
     * 测试Jwt令牌的生成
     */
    @Test
    public void testGenJet() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", 5201314);
        claims.put("name", "THL");
        String jwt=Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "Dawn") //签名算法
                .setClaims(claims)   //自定义内容(载荷部分)
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //设置Jwt令牌有效期为一个小时
                .compact();
        System.out.println(jwt);

    }

Jwt令牌解析

/**
     * 测试令牌的解析
     */
    @Test
    public void testParseJwt(){
        Claims claims=Jwts.parser()
                .setSigningKey("Dawn")
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVEhMIiwiaWQiOjUyMDEzMTQsImV4cCI6MTcyNTAwOTA0NH0.2dz_cOXKMw4js0z7xm8B5X4aaT3diHRup_xLx2Mk4KU")
                .getBody();
        System.out.println(claims);

    }

 

一、工作原理

JWT 由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature)。

  1. 头部:通常包含两部分信息,令牌的类型(即 “JWT”)和所使用的签名算法,如 HMAC SHA256 或 RSA。
  2. 载荷:包含有关用户的声明,例如用户 ID、角色、过期时间等。这些声明被编码为 JSON 对象。
  3. 签名:是使用头部中指定的算法对头部和载荷进行签名生成的。签名的目的是确保令牌在传输过程中没有被篡改。

Base64 是一种编码方式,主要用于将二进制数据编码成 ASCII 字符集的可打印字符,以便在不同的系统和协议中进行传输和存储。 

二、优点

  1. 无状态:服务器不需要保存令牌的状态信息,因为所有必要的信息都包含在令牌本身中。这使得服务器可以更容易地进行扩展,并且减少了服务器的存储需求。
  2. 跨域认证:由于 JWT 是基于 JSON 的开放标准,它可以在不同的域之间进行安全的认证和授权。
  3. 安全性:使用签名机制确保令牌的完整性和真实性,防止令牌被篡改。

三、应用场景

  1. 单点登录(SSO):用户在一个系统中登录后,生成的 JWT 可以在多个相关系统中使用,无需再次登录。
  2. API 授权:在 RESTful API 中,JWT 可以用于验证用户的身份和授权用户对特定资源的访问。
  3. 移动应用:在移动应用中,JWT 可以用于安全地与服务器进行通信,而不需要在每次请求时都传递用户名和密码。

运作过程:

通过Maven引入依赖

        <!--        JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

在测试类中测试生成Jwt令牌

通过链式编程的风格

 /**
     * 测试Jwt令牌的生成
     */
    @Test
    public void testGenJet() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", 18);
        claims.put("name", "THL");
        String jwt=Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "Dawn") //签名算法
                .setClaims(claims)   //自定义内容(载荷部分)
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //设置Jwt令牌有效期为一个小时
                .compact();
        System.out.println(jwt);

    }

 生成的Jwt令牌:

eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVEhMIiwiaWQiOjE4LCJleHAiOjE3MjQ5OTMyMjJ9.98OHK8iRfNxEvPlRuPHO9eAkZKhnqyC6uwRRxB01IXc

在Jwt官网打开解码

 Jwt工具类

package com.traingcase.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;

public class JwtUtils {

    private static String signKey = "Dawn";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    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)
                .getBody();
        return claims;
    }
}

实现带令牌登录的Controller 

package com.traingcase.controller;


import com.traingcase.pojo.Emp;
import com.traingcase.pojo.Result;
import com.traingcase.service.EmpService;
import com.traingcase.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
public class LoginController {
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    //因为用户名和密码每个Emp(员工)都有
    // 所以不用创建新的对象存数据,直接用Emp存
    public Result login(@RequestBody Emp emp){
        log.info("员工登录:{}",emp);
        Emp e=empService.login(emp);
        //登录成功,生成令牌,下发令牌
        if(e!=null){
            Map<String, Object> claims =new HashMap<>();
            claims.put("id",e.getDeptId());
            claims.put("name",e.getName());
            claims.put("username",e.getUsername());
            String jwt=JwtUtils.generateJwt(claims);
            return Result.success(jwt);
        }
        return Result.error("用户名或密码错误");
    }
}

 响应后,令牌会下放到前端

二、过滤器(Filter)

  1. 定义和作用:

    • 过滤器是 Servlet 规范中的一部分,它可以对客户端的请求和服务器的响应进行拦截和处理。
    • 主要用于实现一些通用的功能,如字符编码转换、日志记录、权限验证、数据压缩等。
  2. 工作原理:

    • 当客户端发送请求时,容器会根据配置的过滤器链依次调用过滤器。每个过滤器可以对请求进行处理,然后将请求传递给下一个过滤器或目标资源。
    • 当目标资源处理完请求并生成响应后,响应会沿着过滤器链反向传递,每个过滤器可以对响应进行处理。
  3. 实现方式:

    • 在 Java Web 开发中,可以通过实现 javax.servlet.Filter 接口来创建过滤器。
    • 需要在 web.xml 文件或使用注解进行配置,指定过滤器的作用范围和执行顺序。
  4. 特点:

    • 过滤器是基于函数回调的方式实现的,它是在容器级别对请求和响应进行处理,与具体的业务逻辑相对独立。
    • 可以对所有的请求进行处理,包括静态资源的请求。

代码案例

package com.traingcase.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")

public class DemoFilter implements Filter {
    //初始化方法
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    //拦截到请求之后 调用
    @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();
    }
}

 

@WebFilter(urlPatterns = "/*")注解表明这个过滤器会对所有的请求进行过滤,因为urlPatterns设置为 “/*”,表示匹配所有的 URL 路径。 

  1. servletRequest:表示传入的 Servlet 请求对象,可以通过这个对象获取请求的信息,如请求参数、请求头、请求体等。
  2. servletResponse:表示传出的 Servlet 响应对象,可以在这个对象上设置响应的信息,如响应头、响应体等。
  3. filterChain:表示过滤器链,通过调用filterChain.doFilter(servletRequest, servletResponse)可以将请求传递给下一个过滤器或目标资源进行处理。将请求传递给下一个过滤器(如果有)或目标资源进行处理。这一步非常重要,确保请求能够继续在过滤器链中传递或到达最终的目标资源。

过滤器链

具体代码展现 

package com.traingcase.filter;

import com.alibaba.fastjson.JSONObject;
import com.traingcase.pojo.Result;
import com.traingcase.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter  implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse= (HttpServletResponse) servletResponse;
        //1.获取请求URL
        String url = httpServletRequest.getRequestURI().toString();
        log.info("URL:{}",url);
        //2.判断是不是登录请求,URL是否包含login
        if(url.contains("login")){
            log.info("登录操作,放行");
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //3.获取请求头中的令牌
        String jwt=httpServletRequest.getHeader("token");
        //4.判断令牌是否存在,如果不存在,返回错误结果
        if(jwt==null||jwt.length()==0){
            log.info("请求头token为空");
            Result error=Result.error("NOT_LOGIN");
            //手动转换 对象->JSON-----基于阿里巴巴fastjson工具包
            String notLogin=JSONObject.toJSONString(error);
            httpServletResponse.getWriter().write(notLogin);
            return;
        }
        //5.解析token,如果解析失败,返回错误结果
        //自己设置try catch 看解析能否成功,失败会有异常
        try {
            JwtUtils.parseJWT(jwt);
        }catch (Exception e){
            e.printStackTrace();
            log.info("解析令牌失败");
            Result error=Result.error("NOT_LOGIN");
            //手动转换 对象->JSON-----基于阿里巴巴fastjson工具包
            String notLogin=JSONObject.toJSONString(error);
            httpServletResponse.getWriter().write(notLogin);
            return;
        }

        //6.放行
        log.info("令牌合法,放行");
        filterChain.doFilter(servletRequest,servletResponse);
        return;


    }
}

FASTJSON依赖

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

 

三、拦截器(Interceptor)

  1. 定义和作用:

    • 拦截器是在 Spring Web MVC 等框架中提供的一种机制,用于对请求进行拦截和处理。
    • 主要用于实现一些与业务相关的功能,如用户认证、权限检查、性能监控、日志记录等。
  2. 工作原理:

    • 当客户端发送请求时,请求会先经过 DispatcherServlet,然后 DispatcherServlet 会根据配置的拦截器链依次调用拦截器。每个拦截器可以对请求进行处理,然后将请求传递给下一个拦截器或控制器。
    • 当控制器处理完请求并生成响应后,响应会沿着拦截器链反向传递,每个拦截器可以对响应进行处理。
  3. 实现方式:

    • 在 Spring Web MVC 中,可以通过实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类来创建拦截器。
    • 需要在 Spring 配置文件中进行配置,指定拦截器的作用范围和执行顺序。
  4. 特点:

    • 拦截器是基于 AOP(面向切面编程)的思想实现的,它与具体的业务逻辑结合更紧密。
    • 通常只能对控制器的请求进行处理,不能对静态资源的请求进行处理。

 拦截器类

package com.traingcase.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component //交给IOC容器管理
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override//在目标资源方法运行前运行,true:放行, false:拦截
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle....");
        return true;
    }

    @Override//在目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle....");
    }

    @Override//视图渲染完毕后运行,最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion....");
    }
}

配置类 

package com.traingcase.config;

import com.traingcase.filter.LoginCheckFilter;
import com.traingcase.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {
   @Autowired
   private LoginCheckInterceptor loginCheckInterceptor;

   @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
    }
}

拦截器->拦截路径

 

过滤器和拦截器的区别

  1. 实现方式:

    • 过滤器是 Servlet 规范中的一部分,由容器管理;拦截器是特定框架提供的机制,由框架管理。
    • 过滤器的实现相对简单,只需要实现一个接口;拦截器的实现相对复杂,需要实现特定的接口并进行配置。
  2. 作用范围:

    • 过滤器可以对所有的请求进行处理,包括静态资源的请求;拦截器通常只能对控制器的请求进行处理。
    • 过滤器可以在请求到达目标资源之前和响应返回客户端之后进行处理;拦截器可以在请求到达控制器之前、控制器处理请求之后和响应返回客户端之前进行处理。
  3. 执行顺序:

    • 过滤器的执行顺序是由容器根据配置的过滤器链确定的;拦截器的执行顺序是由框架根据配置的拦截器链确定的。
    • 在 Spring Web MVC 中,拦截器的执行顺序可以通过实现 Ordered 接口或使用 @Order 注解来指定。
  4. 与业务逻辑的耦合度:

    • 过滤器与业务逻辑相对独立,主要用于实现通用的功能;拦截器与业务逻辑结合更紧密,主要用于实现与业务相关的功能。

四、使用场景

  1. 过滤器的使用场景:

    • 字符编码转换:确保所有的请求和响应都使用统一的字符编码。
    • 日志记录:记录请求和响应的详细信息,便于系统的监控和调试。
    • 数据压缩:对响应数据进行压缩,减少网络传输的数据量。
    • 权限验证:对请求进行权限验证,确保只有授权的用户才能访问特定的资源。
  2. 拦截器的使用场景:

    • 用户认证:在请求到达控制器之前进行用户认证,确保用户已经登录。
    • 权限检查:在请求到达控制器之前进行权限检查,确保用户具有访问特定资源的权限。
    • 性能监控:记录请求的处理时间,便于系统的性能优化。
    • 日志记录:记录与业务相关的日志信息,便于系统的业务分析和监控。

过滤器和拦截器都是在 Web 开发中非常有用的技术手段,它们可以帮助我们实现一些通用的和与业务相关的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2090607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《JavaEE进阶》----1.<JavaEE进阶可以学到什么>

本篇博客会讲到 一、JavaEE进阶学习内容&#xff1a; 1.框架的学习&#xff1a;Spring、Spring Boot、Spring MVC、MyBatis 2.大项目实践 3.源码阅读 二、JavaEE简介 B/S架构web开发流程 web前端开发&#xff08;了解&#xff09; web后端开发&#xff08;重点&#xff09; 三、…

properties文件提示未引用

问题描述 以前用的好好的项目,今天突然打开就发现idea不识别spring配置信息显示未引用,如果config代码中引入的配置却可以高亮显示,然后输入spring相关的配置,文件是没有提示的。经过研究发现是spring相关的插件被关闭了。效果如下 解决方法 启用三个插件spring Boot,Sp…

Idea发布springboot项目无法识别到webapp下面的静态资源

问题&#xff1a; Idea发布springboot项目无法识别到webapp下面的静态资源 访问报错404 解决办法&#xff1a; 修改之后重新构建&#xff0c;访问成功

Web3开发与安全:6个月高效学习路径

学习计划概览 总时长&#xff1a;6个月每周学习时间&#xff1a;10-15小时目标&#xff1a;掌握 Solidity 智能合约开发&#xff0c;并具备基本的智能合约安全审计能力。 第一阶段&#xff1a;基础准备&#xff08;第1-2周&#xff09; 1. 区块链基础&#xff08;1周&#x…

workman和GateWay学习笔记

前言 workman支持Udp GateWay是基于workman的二次封装&#xff0c;更适合长链接场景 windows安装workman composer create-project workerman/webman windows运行workman cd webman php windows.php windows访问 http://ip地址:8787 将workman引入thinkphp框架理念

4000字三合一!Stata、SPSS、MATLAB实现多元线性回归详解!

参加数学建模的小伙伴要注意了&#xff1a;多元线性回归几乎是所有分析方式里面最核心、最常用、最全面的模型&#xff0c;博主本科大致参加了10次数模&#xff0c;还有一次正大杯市场调研赛&#xff0c;其中获得拿得出手的奖有9次&#xff0c;有5次都用到了多元线性回归——至…

用Python在PDF文档中创建动作

PDF格式因其跨平台兼容性和丰富的功能集而成为许多行业中的首选文件格式。其中&#xff0c;PDF中的动作&#xff08;Action&#xff09; 功能尤为突出&#xff0c;它允许开发者嵌入交互式元素&#xff0c;如链接、按钮或是更复杂的脚本&#xff0c;从而显著提升文档的互动性和功…

c++vscode多文件实现通讯录管理系统

cvscode多文件实现通讯录管理系统 作为c入门级别的实战项目&#xff0c;此通讯管理系统项目不仅仅是对c入门阶段学习成果的检验&#xff0c;也是对c基础知识的回顾&#xff0c;体会c在实战制作中的思路,是入门c单文件实现通讯录系统的改进 一、多文件通讯录管理系统简介 系统需…

JAVA—多线程

关于线程以及多线程的学习&#xff0c;包括创建和常用方法还有解决线程安全的措施&#xff0c;最后学习线程池和了解并发和并行&#xff0c;对于悲观锁和乐观锁的部分没有学习 目录 1.线程概述 2.多线程的创建 &#xff08;1&#xff09;继承Thread类 &#xff08;2&#…

【GPT】基于GPT_API_free做一个自己的gpt

最终效果 项目背景 秉持能免费就绝不花钱的原则&#xff0c;基于github项目GPT_API_free获取的gpt apikey。下面是简单的代码 import json import os import requestsopenai_url os.getenv("openaiproxy") openai_apikey os.getenv("openaikey") # 初始…

[图解]SysML和EA建模住宅安全系统-活动作为块

1 00:00:00,210 --> 00:00:04,360 下一个步骤是识别潜在的失效 2 00:00:06,850 --> 00:00:11,150 这里它是用一个块定义图来表达的 3 00:00:12,150 --> 00:00:16,790 图17.21&#xff0c;失效模式识别和因果依赖 4 00:00:19,110 --> 00:00:22,400 但是这个块定义…

【AutoX.js】定时器 Timers

文章目录 原文&#xff1a;https://blog.c12th.cn/archives/36.html定时器 Timers笔记实例 最后 原文&#xff1a;https://blog.c12th.cn/archives/36.html 定时器 Timers 笔记 JavaScript Date 参考手册 时间戳 //当前时间戳 log(Math.round(new Date() / 1000));当前星期 …

C语言小tip之函数递归

hello&#xff0c;各位小伙伴们今天我们来学习一下函数递归。 什么是函数递归呢&#xff1f;简单来说就是函数自己来调用自己。函数递归的主要思想是把大事化小&#xff0c;递归包含两层方面&#xff1a;1、递推 2、回归 在使用函数递归的时候要注意包含两个限制条件&#…

SCI英文期刊发表流程

目录 一、撰写初稿二、预审三、英文查重四、Cover letter和Highlights五、英文语法待续 一、撰写初稿 英文好的话应该直接写英文&#xff0c;因为中英文的写法不一样。 而且在这一步把格式修改好&#xff0c;初稿的最终版 二、预审 可以让同学、老师帮看论文&#xff0c;或者…

[Algorithm][综合训练][字符编码][最少的完全平方数][游游的字母串]详细讲解

目录 1.字符编码1.题目链接2.算法原理详解 && 代码实现 2.最少的完全平方数1.题目链接2.算法原理详解 && 代码实现 3.游游的字母串1.题目链接2.算法思路详解 && 代码实现 1.字符编码 1.题目链接 字符编码 2.算法原理详解 && 代码实现 解法&…

Carla自动驾驶仿真十:Carlaviz三维可视化平台搭建

文章目录 前言一、环境准备1、docker安装2、websocket-client安装3、carlaviz代码下载 二、carlaviz使用1、打开carla客户端2、输入启动命令3、进入carlaviz4、修改manual_control.py脚本5、运行manual_control.py脚本6、运行carlaviz官方脚本&#xff08;推荐&#xff09; 前言…

数据库之心:MySQL 探索(一)mysql的安装和基本介绍

欢迎来到我们的MySQL博客&#xff01;在这里&#xff0c;我们将深入探讨MySQL数据库系统的各个方面&#xff0c;包括基础知识、优化技巧、实践案例以及最新的行业趋势。 目录 前言 什么是数据库&#xff1f; 数据库产品 MySQL安装 解压 配置 添加环境变量 初始化MySQL …

计算机毕业设计PySpark+Scrapy高考推荐系统 高考志愿填报推荐系统 高考爬虫 协同过滤推荐算法 Vue.js Django Hadoop 大数据毕设

目  录 第1章 绪论 1.1 研究背景 1.2 国内外现状 1.2.1 国外研究现状 1.2.2 国内研究现状 1.3 主要研究内容 1.4 论文框架结构 第2章 相关开发技术与理论 2.1 前端技术 1&#xff0e;Vue框架技术 2&#xff0e;Element-Plus 2.2 后端技术 1&#xff0e…

linux下cpu多核运行程序以及运行时间统计

一、多核心运行程序 在linux下我们可以指定线程或者进程运行在指定的cpu核心上&#xff0c;操作方法如下&#xff1a; 1&#xff09;运行进程指定cpu核心 taskset -c 2 ./app //-c指定运行的cpu核心号&#xff0c;从0计数&#xff0c;查看效果如下&#xff1a; 2&#xff09…

C++map容器中operator[ ]的实现原理

目录 一、operator[ ]函数介绍 二、insert函数介绍 三、operator[ ]函数实现原理 四、operator[ ]函数功能 一、operator[ ]函数介绍 mapped_type& operator[] (const key_type& k);在map容器中存储的是一个键值对value_type&#xff0c;其本质是pair<const key…