案例01-tlias智能学习辅助系统04-登录认证+全局异常处理

news2025/1/21 18:42:26

目录

1、基础登录

 2、登录校验

2.1、会话跟踪技术:

Cookie、Session

 JWT令牌

2.2、请求过滤

方式一、过滤器(Filter)

方法二:拦截器(interceptor)

Filter与Interceptor的区别 

 3、全局异常处理器


1、基础登录

 2、登录校验

2.1、会话跟踪技术:

Cookie、Session

Cookie和Session 优缺点:

Cookie:优点:HTTP协议中支持的技术

               缺点: -- 移动端APP无法使用Cookie

                           -- 不安全,用户可以自己禁用Cookie(保存在客户端)

                           -- Cookie不能跨域

Session: 优点:存储在服务端,安全

                  缺点:-- 服务器集群环境下无法直接使用Session

                             -- Cookie的所有缺点(Session的底层是Cookie) 

Cookie、Session的设置与获取 :

package pearl.controller;

import pearl.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * Cookie、HttpSession演示
 */
@Slf4j
@RestController
public class CookieSessionController {

    //设置Cookie
    @GetMapping("/c1")
    public Result cookie1(HttpServletResponse response){
        response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie
        return Result.success();
    }

    //获取Cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("login_username")){
                System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie
            }
        }
        return Result.success();
    }

    @GetMapping("/s1")
    public Result session1(HttpSession session){
        log.info("HttpSession-s1: {}", session.hashCode());
        session.setAttribute("loginUser", "tom"); //往session中存储数据
        return Result.success();
    }

    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}", session.hashCode());
        Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
    }
}

访问结果: 

 JWT令牌

JWT官网--详情请参考左边官方资料

JWT令牌技术

优点:-- 支持PC端、移动端

           -- 解决集群环境下的认证问题

           -- 减轻服务器端存储压力

缺点:需要自己实现

 

1、生成JWT令牌 

导入依赖

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

在SpringBoot测试类中新增测试方法,用于生成JWT令牌 

    /*
    * 生成JWT令牌
    * */
    @Test
    public void testGenJwt(){
        Map<String,Object> claims = new HashMap<>(); //定义map集合用于封装自定义的数据
//        集合存数据:语法:mapname.put(key,value)
        claims.put("id",1);
        claims.put("name","tom");
        String jwt = Jwts.builder()//构建JWT令牌 eg:指定生成数字签名的算法、秘钥(自定义)、要存取的自定义的数据
                .signWith(SignatureAlgorithm.HS256, "firstkey")//两个参数:算法,秘钥
                .setClaims(claims)//设置自定义的数据,可以将自定义的数据封装到map集合中
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置令牌截止时间
//        new Date()表示当前时间,里面传入参数表示参数代表的时间,System.currentTimeMillis()表示当前的毫秒数,而加上3600*1000表示一个小时后的时间
                .compact(); //生成字符串类型的令牌
        System.out.println(jwt);
    }

生成运行结果:

eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTY4MjQyOTYzMn0.-iLHjX1bJQzRuSHMrPDU5Xk5Wca3e_12ytZ_weV6GMQ

生成的JWT令牌可在官网中解析出来

 2、解析JWT令牌

在SpringBoot测试类中新增测试方法,用于解析JWT令牌 

    /*
    * 解析JWT令牌
    * */
    @Test
    public void testParseJwt(){
        Claims claims = Jwts.parser()
                .setSigningKey("firstkey")//指定签名秘钥,这里的秘钥和生成JWT令牌是设置的一致
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTY4MjQyOTYzMn0.-iLHjX1bJQzRuSHMrPDU5Xk5Wca3e_12ytZ_weV6GMQ")//传递JWT令牌
                .getBody();//获取JWT令牌的自定义内容
        System.out.println(claims);
    }

运行结果:

{name=tom, id=1, exp=1682429632}

 解析完成!

3、使用JWT令牌登录校验

 这里我们只完成第一步、生成JWT令牌并返回给前端

  • 新建一个工具类JWTutils 存入上方写的生成与解析JWT令牌方法
package pearl.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 = "firstkey";
    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
    /*
    * 登录
    * */
    @PostMapping("/login")
    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.getId());
            claims.put("name",e.getName());
            claims.put("username",e.getUsername());
            String jwt = JwtUtils.generateJwt(claims);//jwt包含当前登录的员工信息
            return Result.success(jwt);
        }

//        登录失败,返回错误信息

        return Result.error("用户名或密码错误");
    }
}

在这个案例中,我们选择使用JWT令牌进行会话跟踪

2.2、请求过滤

方式一、过滤器(Filter)

-- 概念: Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一。

-- 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。

-- 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

Filter 快速入门

步骤:

1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法。

2.配置Filter: Filter类上加@WebFilter注解,配置拦截资源的路径。启动类上加

@ServletComponentScan开启Servlet组件支持。

 filter类:

package pearl.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 {
        System.out.println("init 初始化方法执行了");
    }

    @Override//拦截到请求后调用,会执行多次
    public void doFilter(ServletRequest Req, ServletResponse Res, FilterChain fChain) throws IOException, ServletException {
        System.out.println("拦截到了请求");
        System.out.println("放行前的逻辑");
//        放行
        fChain.doFilter(Req,Res);
        System.out.println("放行后的逻辑");

    }

    @Override //销毁方法,只执行一次
    public void destroy() {
        System.out.println("destroy 销毁方法执行了");
    }
}

启动类:

 过滤器链:

filter 实现登录校验 

  • 导入依赖:
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
  • 创建一个类,LoginFilter
package pearl.filter;

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

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 LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest Request, ServletResponse Response, FilterChain fChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)Request;
        HttpServletResponse response = (HttpServletResponse)Response;
        // 1. 获取请求url
        String url = request.getRequestURI();
        log.info("请求的url: {}",url);
        // 2. 判断请求中是否包含login,如果包含,说明是登录操作,放行
        if (url.contains("login")){
            log.info("登录操作,放行");
            fChain.doFilter(request,response);
            return;
        }
        // 3. 获取请求中的令牌(token)
        String jwt = request.getHeader("token");
        // 4. 判断领牌是否存在,如果不存在,返回错误结果(未登录)
        if (jwt == null || jwt ==""){
            log.info("请求头token为空,返回错误结果");
            Result error = Result.error("NOT_LOGIN");
            //将对象强转为Json
            String notLogin = JSONObject.toJSONString(error);
            response.getWriter().write(notLogin);// 相应数据
            return;
        }
        // 5. 解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);  //jwt令牌解析报错说明,解析失败,返回错误结果
        } catch (Exception e) {
            e.printStackTrace();
            Result error = Result.error("NOT_LOGIN");
            //将对象强转为Json
            String notLogin = JSONObject.toJSONString(error);
            response.getWriter().write(notLogin);// 相应数据
            return;
        }
        // 6. 放行
        log.info("令牌合法,放行");
        fChain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

完成!

方法二:拦截器(interceptor)

概念:   是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦             截控制器方法的执行。

作用:   拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。

interceptor 快速入门

        -- 定义拦截器,实现Handlerlnterceptor接口,并重写其所有方法。

package pearl.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
public class LoginInterceptor implements HandlerInterceptor {
    @Override//controller方法运行之前运行,返回true放行,否则,不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)throws Exception{
        System.out.println("preHandle...");
        return true;
    }

    @Override // controller方法执行之后执行
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

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

        -- 注册拦截器

package pearl.config;

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;
import pearl.interceptor.LoginInterceptor;

@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;  //定义一个拦截器对象

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");//这里需注意,拦截所有请求的路径是`/**`
    }
}

 拦截路径

 执行流程

interceptor 实现登录校验

         -- 定义拦截器,实现Handlerlnterceptor接口,并重写其所有方法。

package pearl.interceptor;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import pearl.pojo.Result;
import pearl.utils.JwtUtils;

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

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override//controller方法运行之前运行,返回true放行,否则,不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)throws Exception{

        // 1. 获取请求url
        String url = req.getRequestURI();
        log.info("请求的url: {}",url);
        // 2. 判断请求中是否包含login,如果包含,说明是登录操作,放行
        if (url.contains("login")){
            log.info("登录操作,放行");
            return true;
        }
        // 3. 获取请求中的令牌(token)
        String jwt = req.getHeader("token");
        // 4. 判断领牌是否存在,如果不存在,返回错误结果(未登录)
        if (jwt == null || jwt ==""){
            log.info("请求头token为空,返回错误结果");
            Result error = Result.error("NOT_LOGIN");
            //将对象强转为Json
            String notLogin = JSONObject.toJSONString(error);
            res.getWriter().write(notLogin);// 相应数据
            return false;
        }
        // 5. 解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);  //jwt令牌解析报错说明,解析失败,返回错误结果
        } catch (Exception e) {
            e.printStackTrace();
            Result error = Result.error("NOT_LOGIN");
            //将对象强转为Json
            String notLogin = JSONObject.toJSONString(error);
            res.getWriter().write(notLogin);// 相应数据
            return false;
        }
        // 6. 放行
        log.info("令牌合法,放行");
        return true;
    }

    @Override // controller方法执行之后执行
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }

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

   -- 注册拦截器

package pearl.config;

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;
import pearl.interceptor.LoginInterceptor;

@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;  //定义一个拦截器对象

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login");//这里需注意,拦截所有请求的路径是`/**`
    }
}

Filter与Interceptor的区别 

接口规范不同:  过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。
拦截范围不同:  过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。

 3、全局异常处理器

新建包--exception ,在包中新建类  GlobalException

package pearl.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import pearl.pojo.Result;

/*
* 全局异常处理器
* */

@RestControllerAdvice // 会将结果封装成json格式
public class GlobalException {

    @ExceptionHandler(Exception.class)  //Exception.class表示捕获所有异常
    public Result ex(Exception ex){
        ex.printStackTrace();
        return Result.error("对不起,操作失败,请联系管理员");
    }
}

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

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

相关文章

fork函数如何创建进程,exit/_exit函数如何使进程终止的详细分析与代码实现

&#x1f38a;【进程通信与并发】专题正在持续更新中&#xff0c;进程&#xff0c;线程&#xff0c;IPC&#xff0c;线程池等的创建原理与运用✨&#xff0c;欢迎大家前往订阅本专题&#xff0c;获取更多详细信息哦&#x1f38f;&#x1f38f;&#x1f38f; &#x1fa94;本系列…

【Pytorch基础教程38】torchserve模型部署和推理

note torch-model-archiver打包模型&#xff1b;利用torchserve加载前面打包的模型&#xff0c;并以grpc和http等接口往外提供推理服务启动模型的api服务、curl命令发送http post请求&#xff0c;请求模型服务API&#xff1b;流程和TensorFlow serving流程大同小异 文章目录 n…

人工智能之配置环境教程二:在Anaconda中创建虚拟环境并在VsCode中使用

人工智能之配置环境教程二&#xff1a;在Anaconda中创建虚拟环境安装pytorch并在VsCode中使用虚拟环境 作者介绍一. 在Anaconda中创建虚拟环境1. 进入本地终端1.1 键盘使用**winR**快捷键1.2 输入**cmd**点击**确定**进入windows命令行终端 2. 安装镜像源2.1 添加镜像源 3. 创建…

PowerShell install 一键部署http+用户名密码登录实现文件系统

Apache 前言 Apache(音译为阿帕奇)是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上&#xff0c;由于其跨平台和安全性被广泛使用&#xff0c;是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充&#xff0c;将Perl/Python等…

BUUCTF [第五空间2019 决赛]PWN5

小白垃圾做题笔记而已&#xff0c;不建议阅读。 简书上的大佬有三种解题思路&#xff0c;而我刚开始一种也不会&#xff0c;看了题解后才勉强有了两种。 1.第一种算绕过if吧。 更改dword_804C044中的内容&#xff0c;第二次输出相同的内容&#xff0c;从而绕过if 脚本如下&…

Linux-安装gcc和g++报错降级的解决方法

一、简介 通过sudo apt-get install gcc指令安装g报错。 下列软件包有未满足的依赖关系&#xff1a;gcc : 依赖: gcc-7 (> 7.3.0-12~) 但是它将不会被安装推荐: libc6-dev 但是它将不会被安装 或libc-dev又按照网上的解决办法 &#xff0c;还是报错。 apt-get update apt-g…

ESET NOD32 互联网安全软件和防毒软件 -简单,可靠的防护。

安全防范病毒和间谍软件&#xff0c;银行和网上购物更安全, 网络摄像头和家用路由器使用更安全&#xff0c;阻止黑客访问您的电脑, 让您的孩子网络安全&#xff1b;产品兑换码仅支持中国ip地址兑换&#xff0c;兑换后可全球通用。 简单&#xff0c;可靠的防护 防范黑客&#x…

【C++11】新的类功能、可变参数模板

C11——新的类功能、可变参数模板 文章目录 C11——新的类功能、可变参数模板一、新的类功能1.测试代码2.默认成员函数3.类成员变量初始化4.强制生成默认函数的关键字default5.禁止生成默认函数的关键字delete6.继承和多态中的final与override关键字 二、可变参数模板1.可变参数…

第64章 树型结构数据的前端渲染渲染显示示例

1 \src\views\TreeTestView.vue <template> <div class"wrap"> <!--注意&#xff1a;1、“回到顶部”组件及其回滚内容都必须包含到同1个div容器中。--> <!-- 2、div容器中必须有1个唯1性的样式类&#xff08;例如&#xff1a;wrap&#xff09…

【Kubenetes进阶】Helm3保姆级安装与Chart使用

之前在Centos 7_64位上实现了用kubespray-2.15.0完成kubenetes的部署&#xff0c;对于kubenetes&#xff0c;Helm无疑是一个良好的命令行下的客户端工具。Helm主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。 需要对helm加深了…

安全狗云安全资源池为运营商行业云降本增效

随着政府大力促进数字化转型&#xff0c;网络安全作为数字化建设的安全基石&#xff0c;已然成为保障数字化过程中稳定运行的重要因素。 一 严峻挑战下用户亟需安全托管专业服务 1) 云计算虚拟化的存储、部署及运作模式&#xff0c;数据所有权与管理权分离等特点&#xff0c…

【iOS】—— KVO再学习

KVO 文章目录 KVOKVO概念KVO使用步骤注册KVO监听KVO监听实现移除KVO监听 KVO基本用法KVO传值禁止KVO的方法使用注意事项 KVO原理GSKVOInfoGSKVOPathInfoGSKVOObservation为什么要重写class方法呢&#xff1f; GSKVOReplacementGSKVOBaseGSKVOBase小结 源码实现移除观察者总结 K…

unity Shader实现半透明阴影

在shader中&#xff0c;要对移动端的兼容&#xff0c;还不想实现两套分开兼容的话&#xff0c; #pragma exclude_renderers gles gles3 glcore #pragma target 4.5这两句话一定要改掉&#xff0c;第一行代码直接剔除了gles的渲染&#xff0c;而恰恰大部分移动端都是用的gles&a…

第十七章 访问者模式

文章目录 前言一、访问者模式基本介绍二、访问者模式应用实例完整代码评测抽象类 Action成功评价 Success失败评价评价人抽象类男性女性数据结构&#xff0c;管理很多人评价Clint 测试添加 wait 选票clint 测试 三、访问者模式的注意事项和细节 前言 一、访问者模式基本介绍 二…

Vue2 脚手架下载及配置淘宝镜像--和ieda的配置和打开

目录 Vue2 脚手架下载及配置淘宝镜像 为什么需要 Vue Cli 脚手架? 环境配置&#xff0c;搭建项目 1. 搭建 Vue2 脚手架工程&#xff0c; 2.查看 3.冲突 4. 下载 5. 安装 6. 验证 7. 先删除以前的 cli 版本<不论是之前未下载或没有下载> 8. 安装淘宝镜像-cnpm…

20230427配置cv1826的buildroot在串口免登录的方法二

20230427配置cv1826的buildroot在串口免登录的方法二 2023/4/27 16:46 进度&#xff1a;可以拿掉密码&#xff0c;但是无法拿掉用户名&#xff01; 1、 Z:\buildroot1\buildroot\configs\cvitek_cv182x_defconfig BR2_TOOLCHAIN_EXTERNAL_GCC_6y BR2_TOOL…

编译一个魔兽世界开源服务端Windows需要安装什么环境

编译一个魔兽世界开源服务端Windows需要安装什么环境 大家好我是艾西&#xff0c;去年十月份左右wy和bx发布了在停服的公告。当时不少小伙伴都在担心如果停服了怎么办&#xff0c;魔兽这游戏伴随着我们渡过了太多的时光。但已经发生的事情我们只能顺其自然的等待GF的消息就好了…

Selenium基础篇之键盘操作(一)

文章目录 前言一、常用方法(上)二、小剧场2.1场景2.2代码2.2.1引入库2.2.2启动浏览器实例2.2.3访问C站首页2.2.4窗口最大化2.2.5获取输入框元素2.2.6向输入框输入文字2.2.7使用退格键删除最后一个字符2.2.8全选输入框文字2.2.9剪切输入框文字2.2.10粘贴文字到输入框2.2.11回车查…

经验分享 | 科研行业如何搭建RASP防护体系?

多年来&#xff0c;开源网安长期服务金融、政府、科技等大型企业&#xff0c;针对不同实际应用场景&#xff0c;打造出了成熟落地的解决方案&#xff0c;提高并完善了企业安全防护技术与管理体系。今天&#xff0c;我们就来了解开源网安是如何为科研行业搭建RASP防护体系的。 科…

“ ES6+ —— 让你的JavaScript代码从平凡到精彩 “

前期回顾 【提高代码可读性】—— 手握多个代码优化技巧、细数哪些惊艳一时的策略_0.活在风浪里的博客-CSDN博客代码优化对象策略https://blog.csdn.net/m0_57904695/article/details/128318224?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%…