Spring Security 详解

news2024/11/26 20:21:51

目录

    • 一、Spring Security简介
      • 1.1 概述
      • 1.2 历史
    • 二、Spring Security功能
    • 三、Spring Security支持的身份认证模式
    • 四、SpringBoot项目构建
      • 4.1 项目搭建
      • 4.2 内存认证
      • 4.3 UserDetailsService 处理逻辑
      • 4.4 数据库认证
      • 4.5 PasswordEncoder
      • 4.6 自定义登录页面
      • 4.7 会话管理
      • 4.8 认证成功后的处理方式
      • 4.9 认证失败后的处理方式
      • 4.10 退出登录

在web应用开发中,安全无疑是十分重要的,选择Spring Security来保护web应用是一个非常好的选择。Spring Security 是spring项目之中的一个安全模块,可以非常方便与spring项目无缝集成。特别是在spring boot项目中加入spring security更是十分简单。本篇我们介绍spring security,以及spring security在web应用中的使用。
请添加图片描述

一、Spring Security简介

1.1 概述

Spring Security是一个高度自定义的安全框架。利用Spring IoC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。

使用Spring Secruity的原因有很多,但大部分都是发现了javaEE的Servlet规范或EJB规范中的安全功能缺乏典型企业应用场景。同时认识到他们在WAR或EAR级别无法移植。因此如果你更换服务器环境,还有大量工作去重新配置你的应用程序。使用Spring Security 解决了这些问题,也为你提供许多其他有用的、可定制的安全功能。

Spring Security是Spring项目组提供的安全服务框架,核心功能包括认证和授权。它为系统提供了声明式安全访问控制功能,减少了 为系统安全而编写大量重复代码的工作。

1.2 历史

Spring Security 以“The Acegi Secutity System for Spring” 的名字始于2003年年底。其前身为acegi项目。起因是Spring开发者邮件列表中一个问题,有人提问是否考虑提供一个基于Spring的安全实现。限制于时间问题,开发出了一个简单的安全实现,但是并没有深入研究。几周后,Spring社区中其他成员同样询问了安全问题,代码提供给了这些人。2004年1月份已经有20人左右使用这个项目。随着更多人的加入,在2004年3月左右在sourceforge中建立了一个项目。在最开始并没有认证模块,所有的认证功能都是依赖容器完成的,而acegi则注重授权。但是随着更多人的使用,基于容器的认证就显现出了不足。acegi中也加入了认证功能。大约1年后acegi成为Spring子项目。在2006年5月发布了acegi 1.0.0版本。2007年底acegi更名为Spring Security。

二、Spring Security功能

Spring Security 的核心功能主要包括如下几个:

  • 认证 :认证即系统判断用户的身份是否合法,合法可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名密码登录、二维码登录、手机短信登录、脸部识别认证、指纹认证等方式。 认证是为了保护系统的隐私数据与资源,用户的身份合法才能访问该系统的资源。
  • 授权:授权即认证通过后,根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。 比如在一些视频网站中,普通用户登录后只有观看免费视频的权限,而VIP用户登录后,网站会给该用户提供观看VIP视频的权限。 认证是为了保证用户身份的合法性,授权则是为了更细粒度的对隐私数据进行划分,控制不同的用户能够访问不同的资源。
  • 防护攻击:防止身份伪造等各种攻击手段。
  • 加密功能:对密码进行加密、匹配等。
  • 会话功能:对Session进行管理。
  • RememberMe功能:实现“记住我”功能,并可以实现token令牌持久化。

三、Spring Security支持的身份认证模式

在身份验证层面,Spring Security广泛支持各种身份认证模式。这些验证模式绝大多数都是由第三方提供,或相关标准组织提供的,目前Spring Security支持如下认证技术:

  • HTTP BASIC authentication headers: 一个基于IEFT RFC的标准。
  • HTTP Digest authentication headers: 一个基于IETF RFC的标准。
  • HTTP X.509 client certificate exchange: 一个基于IETF RFC的标准。
  • LDAP: 一种常见的跨平台身份验证方式。
  • Form-based authentication: 用于简单的用户界面需求。
  • OpenID authentication: 一种去中心化的身份认证方式。
  • Authentication based on pre-established request headers: 类似于 Computer Associates SiteMinder,一种用户身份验证及授权的集中式安全基础方案。
  • Jasig Central Authentication Service: 单点登录方案。
  • Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker: 一个Spring远程调用协议。
  • Automatic "remember-me" authentication: 允许在指定到期时间前自行重新登录系统。
  • Anonymous authentication: 允许匿名用户使用特定的身份安全访问资源。
  • Run-as authentication: 允许在一个会话中变换用户身份的机制。
  • Java Authentication and Authorization Service: JAAS,Java验证和授权API.
  • Java EE container authentication: 允许系统继续使用容器管理这种身份验证方式。
  • Kerberos: 一种使用对称密钥机制,允许客户端与服务器相互确认身份的认证协议。

四、SpringBoot项目构建

4.1 项目搭建

  • 准备一个名为 mysecurity 的Mysql数据库

  • 创建SpringBoot项目,添加依赖

    <!-- SpringMVC -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--Thymeleaf-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!--Spring Security-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- Mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- MyBatisPlus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.0</version>
    </dependency>
    <!-- spring session redis -->
    <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- junit -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
  • 编写配置文件

    server:
      port: 80
    #日志格式
    logging:
      pattern:
        console: '%d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread] %cyan(%-50logger{50}):%msg%n'
    # 数据源
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql:///mysecurity?serverTimezone=UTC
        username: root
        password01: root
    
  • 在 template 文件夹编写项目主页面 main.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>主页面</title>
    </head>
    <body>
        <h1>主页面</h1>
    </body>
    </html>
    
  • 编写访问页面控制器

    @Controller
    public class PageController {
        @RequestMapping("/{page}")
        public String showPage(@PathVariable String page){
            return page;
       }
    }
    
  • 启动项目,访问项目主页面http://localhost/main,项目会自动跳转到一个登录页面。这代表Spring Security已经开启了认证功能,不登录无法访问所有资源,该页面就是Spring Security 自带的登录页面。 我们使用 user 作为用户名,控制台中的字符串作为密码登录,登录成功后跳转到项目主页面。

4.2 内存认证

在实际开发中,用户数量不会只有一个,且密码是自己设置的。所以我们需要自定义配置用户信息。首先我们在内存中创建两个用户,Spring Security会将登录页传来的用户名密码和内存中用户名密码做匹配认证。

// Security配置类
@Configuration
public class SecurityConfig {
    // 定义认证逻辑
    @Bean
    public UserDetailsService userDetailsService(){
        // 1.使用内存数据进行认证
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        // 2.创建两个用户
        UserDetails user1 = User.withUsername("lt").password("123").authorities("admin").build();
        UserDetails user2 = User.withUsername("lt2").password("456").authorities("admin").build();
        // 3.将这两个用户添加到内存中
        manager.createUser(user1);
        manager.createUser(user2);
        return manager;
   }
    //密码编码器,不解析密码
    @Bean
    public PasswordEncoder passwordEncoder()
   {
        return NoOpPasswordEncoder.getInstance();
   }
}

此时进行认证测试,我们可以将登录页传来的用户名密码和内存中 用户名密码做匹配认证。

4.3 UserDetailsService 处理逻辑

在实际项目中,认证逻辑是需要自定义控制的。将 UserDetailsService 接口的实现类放入Spring容器即可自定义认证逻辑。 InMemoryUserDetailsManager 就是 UserDetailsService 接口的一个实现类,它将登录页传来的用户名密码和内存中用户名密码做匹配认证。当然我们也可以自定义 UserDetailsService 接口的实现类。

public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

UserDetailsService 的实现类必须重写 loadUserByUsername 方法,该方法定义了 具体的认证逻辑,参数 username 是前端传来的用户名,我们需要根据传来的用户名查询到该用户(一般是从数据库查询),并将查询到的用户封装成一个UserDetails对象,该对象是Spring Security提供的用户对象,包含用户名、密码、权限。Spring Security会根据 UserDetails对象中的密码和客户端提供密码进行比较。相同则认证通过,不相同则认证失败。
在这里插入图片描述

4.4 数据库认证

  • 准备数据库数据

    CREATE TABLE `users`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255),
      `password` varchar(255) ,
      `phone` varchar(255) ,
      PRIMARY KEY (`id`)
    );
    INSERT INTO `users` VALUES (1, 'lt','lt1', '15012345678');
    INSERT INTO `users` VALUES (2, '蓝天','lt2', '15012345678');
    
  • 编写用户实体类

    @Data
    public class Users {
        private Integer id;
        private String username;
        private String password;
        private String phone;
    }
    
  • 编写dao接口

    public interface UsersMapper extends BaseMapper<Users> {}
    
  • 在SpringBoot启动类中添加 @MapperScan 注解,扫描Mapper文件夹

    @SpringBootApplication
    @MapperScan("com.lt.myspringsecurity.mapper")
    public class MysecurityApplication {
        public static void main(String[] args)
         {
            SpringApplication.run(MysecurityApplication.class, args);
       }
    }
    
  • 创建 UserDetailsService 的实现类,自定义认证逻辑

    @Service
    public class MyUserDetailsService
    implements UserDetailsService {
        @Autowired
        private UsersMapper usersMapper;
        // 自定义认证逻辑
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // 1.构造查询条件
            QueryWrapper<Users> wrapper = new QueryWrapper<Users>().eq("username",username);
            // 2.查询用户
            Users users = usersMapper.selectOne(wrapper);
            // 3.封装为UserDetails对象
            UserDetails userDetails = User
                   .withUsername(users.getUsername())
                   .password(users.getPassword())
                   .authorities("admin")
                   .build();
            // 4.返回封装好的UserDetails对象
            return userDetails;
       }
    }
    
  • 测试连接数据库认证

4.5 PasswordEncoder

在实际开发中,为了数据安全性,在数据库中存放密码时不会存放 原密码,而是会存放加密后的密码。而用户传入的参数是明文密 码。此时必须使用密码解析器才能将加密密码与明文密码做比对。 Spring Security中的密码解析器是 PasswordEncoder 。
Spring Security要求容器中必须有 PasswordEncoder 实例,之前使用的
NoOpPasswordEncoder 是 PasswordEncoder 的实现类,意思是不解析密码,使用明文密码。
Spring Security官方推荐的密码解析器是 BCryptPasswordEncoder。

@SpringBootTest
public class PasswordEncoderTest {
    @Test
    public void testBCryptPasswordEncoder(){
        //创建解析器
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        //密码加密
        String password = encoder.encode("lt1");
        System.out.println("加密后:"+password);
        //密码校验
        /**
         * 参数1:明文密码
         * 参数2:加密密码
         * 返回值:是否校验成功
         */
        boolean result = encoder.matches("lt1","$2a$10$/MImcrpDO21HAP2amayhme8j2SM0YM50");
        System.out.println(result);
   }
}

在开发中,我们将 BCryptPasswordEncoder 的实例放入Spring容器即可,并 且在用户注册完成后,将密码加密再保存到数据库。

//密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

4.6 自定义登录页面

虽然Spring Security给我们提供了登录页面,但在实际项目中,更多的是使用自己的登录页面。Spring Security也支持用户自定义登录页面。用法如下:

  • 编写登录页面

  • 在Spring Security配置类自定义登录页面

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        //Spring Security配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // 自定义表单登录
            http.formLogin()
               .loginPage("/login.html") //自定义登录页面
               .usernameParameter("username")// 表单中的用户名项
               .passwordParameter("password")// 表单中的密码项
               .loginProcessingUrl("/login")
              // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法
               .successForwardUrl("/main")//登录成功后跳转的路径
               .failureForwardUrl("/fail");//登录失败后跳转的路径
              // 需要认证的资源
              http.authorizeRequests().antMatchers("/login.html").permitAll() 
              //登录页不需要认证
               .anyRequest().authenticated();
              //其余所有请求都需要认证
            //关闭csrf防护
            http.csrf().disable();
       }
        @Override
        public void configure(WebSecurity web) throws Exception {
            // 静态资源放行
          web.ignoring().antMatchers("/css/**");
       }
    }
    
  • CSRF防护
    CSRF:跨站请求伪造,通过伪造用户请求访问受信任的站点从而进行非法请求访问,是一种攻击手段。 Spring Security 为了防止CSRF攻击,默认开启了CSRF防护,这限制了除了 GET请求以外的大多数方法。我们要想正常使用Spring Security需要突破CSRF防护。解决方法如下:

    • 方法一:关闭CSRF防护

      http.csrf().disable();
      
    • 方法二:突破CSRF防护
      CSRF为了保证不是其他第三方网站访问,要求访问时携带参 数名为_csrf值为令牌,令牌在服务端产生,如果携带的令牌 和服务端的令牌匹配成功,则正常访问。

      <form class="form" action="/login" method="post">
      <!-- 在表单中添加令牌隐藏域 -->
         <input type="hidden" th:value="${_csrf.token}" name="_csrf" th:if="${_csrf}"/>
         <input type="text" placeholder="用户名" name="username">
         <input type="password" placeholder="密码" name="password">
         <button type="submit">登录</button>
      </form>
      

4.7 会话管理

用户认证通过后,有时我们需要获取用户信息,比如在网站顶部显示:欢迎您,XXX。Spring Security将用户信息保存在会话中,并提供会话管理,我们可以从 SecurityContext 对象中获取用户信息, SecurityContext 对象与当前线程进行绑定。获取用户信息的写法如下:

@RestController
public class MyController {
    // 获取当前登录用户名
    @RequestMapping("/users/username")
    public String getUsername(){
        // 1.获取会话对象
        SecurityContext context = SecurityContextHolder.getContext();
        // 2.获取认证对象
        Authentication authentication = context.getAuthentication();
        // 3.获取登录用户信息
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        return userDetails.getUsername();
   }
}

4.8 认证成功后的处理方式

登录成功后,如果除了跳转页面还需要执行一些自定义代码时, 如:统计访问量,推送消息等操作时,可以自定义登录成功处理器。

  • 自定义登录成功处理器
    public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, 
        HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            // 拿到登录用户的信息
            UserDetails userDetails = (UserDetails)authentication.getPrincipal();
            System.out.println("用户名:"+userDetails.getUsername());
            System.out.println("一些操作...");
            // 重定向到主页
            response.sendRedirect("/main");
       }
    }
    
  • 配置登录成功处理器
    http.formLogin() // 使用表单登录
       .loginPage("/login.html") // 自定义登录页面
       .usernameParameter("username") // 表单中的用户名项
       .passwordParameter("password") // 表单中的密码项
       .loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行 UserDetailsService的方法
        //.successForwardUrl("/main") //登录成功后跳转的路径
       .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
       .failureForwardUrl("/fail"); //登录失败后跳转的路径
    

4.9 认证失败后的处理方式

登录失败后,如果除了跳转页面还需要执行一些自定义代码时, 如:统计失败次数,记录日志等,可以自定义登录失败处理器。

  • 自定义登录失败处理器

    public class MyLoginFailureHandler implements AuthenticationFailureHandler {
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
    AuthenticationException exception) throws IOException, ServletException {
            System.out.println("记录失败日志...");
            response.sendRedirect("/fail");
       }
    }
    
  • 配置登录失败处理器

    http.formLogin() // 使用表单登录
       .loginPage("/login.html") // 自定义登录页面
       .usernameParameter("username") // 表单中的用户名项
       .passwordParameter("password") // 表单中的密码项
       .loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法
        //.successForwardUrl("/main") //登录成功后跳转的路径
       .successHandler(new MyLoginSuccessHandler()) //登录成功处理器
        //.failureForwardUrl("/fail") //登录失败后跳转的路径
       .failureHandler(new MyLoginFailureHandler()); //登录失败处理器
        // 需要认证的资源
    http.authorizeRequests()
       .antMatchers("/login.html").permitAll() //登录页不需要认证
       .antMatchers("/fail").permitAll() //失败页不需要认证
       .anyRequest().authenticated(); //其余所有请求都需要认证
    

4.10 退出登录

在系统中一般都有退出登录的操作。退出登录后,Spring Security 进行了以下操作:

  • 清除认证状态
  • 销毁HttpSession对象
  • 跳转到登录页面

在Spring Security中,退出登录的写法如下:

  • 配置退出登录的路径和退出后跳转的路径

    // 退出登录配置
    http.logout()
       .logoutUrl("/logout") // 退出登录路径
       .logoutSuccessUrl("/login.html") // 退出登录后跳转的路径
       .clearAuthentication(true) //清除认证状态,默认为true
       .invalidateHttpSession(true); // 销毁HttpSession对象,默认为true
    
  • 在网页中添加退出登录超链接

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>主页面</title>
    </head>
    <body>
      <h1>主页面</h1>
      <a href="/logout">退出登录</a>
    </body>
    </html>
    

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

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

相关文章

添加SQLCipher 到项目中

文章目录 一、克隆下载SQLCipher二、手动导入1. 生成sqlite3.c2. 在项目中添加命令3. 添加 Security.framework 三、CocoaPods导入 SQLCipher官方地址 一、克隆下载SQLCipher $ cd ~/Documents/code $ git clone https://github.com/sqlcipher/sqlcipher.git二、手动导入 1.…

Qt5兼容使用之前Qt4接口 intersect接口

1. 问题 项目卡中遇到编译报错&#xff0c; 错误 C2039 “intersect”: 不是“QRect”的成员 。 2. 排查过程 排查到依赖的第三方代码&#xff0c;使用 intersect 接口&#xff0c; 跟踪排查到头文件中使用了***#if QT_DEPRECATED_SINCE(5, 0)*** #if QT_DEPRECATED_SINCE…

大学生创业运营校园跑腿小程序怎么样?

校园跑腿小程序是一种基于移动互联网的服务平台&#xff0c;旨在为大学生提供便捷的跑腿服务。它可以连接大学生用户和需要代办事务的人群&#xff0c;实现多方共赢的局面。接下来&#xff0c;我将从需求背景、市场前景、功能特点等方面进行分析。 首先&#xff0c;校园跑腿小程…

ETLCloud+MaxCompute实现云数据仓库的高效实时同步

MaxCompute介绍 MaxCompute是适用于数据分析场景的企业级SaaS&#xff08;Software as a Service&#xff09;模式云数据仓库&#xff0c;以Serverless架构提供快速、全托管的在线数据仓库服务&#xff0c;消除了传统数据平台在资源扩展性和弹性方面的限制&#xff0c;最小化用…

TransNetR:用于多中心分布外测试的息肉分割的基于transformer的残差网络

TransNetR Transformer-based Residual Network for Polyp Segmentation with Multi-Center Out-of-Distribution Testing 阅读笔记 1. 论文名称 《TransNetR Transformer-based Residual Network for Polyp Segmentation with Multi-Center Out-of-Distribution Testing》 用…

STM32基于CubeIDE和HAL库 基础入门学习笔记:物联网项目开发流程和思路

文章目录&#xff1a; 第一部分&#xff1a;项目开始前的计划与准备 1.项目策划和开发规范 1.1 项目要求文档 1.2 技术实现文档 1.3 开发规范 2.创建项目工程与日志 第二部分&#xff1a;调通硬件电路与驱动程序 第三部分&#xff1a;编写最基础的应用程序 第四部分&…

JAVA毕业设计093—基于Java+Springboot+Vue的招聘系统(源码+数据库)

基于JavaSpringbootVue的招聘系统(源码数据库)093 一、系统介绍 本系统前后端分离 本系统分为管理员、HR、用户三种角色 用户角色包含以下功能&#xff1a; 登录、注册、简历(搜索、投递和收藏)、hr联系、我的关注、我的收藏、我的简历、简历投递管理、面试管理、个人中心…

zabbix5.0安装教程(超详细)实测完美可用

5.0 版本对基础环境的要求有⼤的变化&#xff0c;最⼤的就是对 php 版本的要求&#xff0c;最低要求7.2.0 版本,对 php 扩展组件版本也有要求&#xff0c;详见官网文档 https://www.zabbix.com/documentation/current/manual/installation/requirements 准备好⼀台linux服务器&…

day23-113. 路径总和ii

113. 路径总和ii 力扣题目链接(opens new window) 给定一个二叉树和一个目标和&#xff0c;找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 思路 利用…

【团队协作开发】IDEA中Git从远程其他分支拉取代码并同步更新到自己的分支中更新不全问题解决

出现这个问题往往是因为没有先拉取远程分支的最新变化到本地导致的&#xff0c;具体操作流程和解决方法如下&#xff1a; 1、首先&#xff0c;先确保本地有一个和远程要拉取分支(比如dev_z)相关联的分支&#xff0c;如果没有&#xff1a;选择远程要拉取的分支&#xff0c;点击C…

postman官网下载安装登录详细教程

目录 一、介绍 二、官网下载 三、安装 四、注册登录postman账号&#xff08;不注册也可以&#xff09; postman注册登录和不注册登录的使用区别 五、关于汉化的说明 一、介绍 简单来说&#xff1a;是一款前后端都用来测试接口的工具。 展开来说&#xff1a;Postman 是一个…

探讨C语言是否仍然满足现代编程需求

在过去的30年里&#xff0c;有人试图通过引入一门新的语言来取代C语言&#xff0c;其中一位被简称为BS的人也持有类似观点。尽管这门新语言在某些方面表现出色&#xff0c;但它并未能完全取代C语言&#xff0c;而是在特定领域发展出自己的优势。此后&#xff0c;又有一家公司决…

在线Word怎么转换成PDF?Word无法转换成PDF文档原因分析

不同的文件格式使用方法是不一样的&#xff0c;而且也需要使用不同的工具才可以打开编辑内容&#xff0c;针对不同的场合用户们难免会用到各种各样的文件格式&#xff0c;要想在不修改内容的前提下提高工作效率&#xff0c;那就需要用到文件格式转换&#xff0c;那么在线Word怎…

苍穹外卖项目解读(四) 微信小程序支付、定时任务、WebSocket

前言 HM新出springboot入门项目《苍穹外卖》&#xff0c;笔者打算写一个系列学习笔记&#xff0c;“苍穹外卖项目解读”&#xff0c;内容主要从HM课程&#xff0c;自己实践&#xff0c;以及踩坑填坑出发&#xff0c;以技术&#xff0c;经验为主&#xff0c;记录学习&#xff0…

爬虫018_urllib库_cookie反爬_post请求百度翻译获取百分翻译内容_以及详细翻译内容---python工作笔记037

然后我们来看如何用urllib发送post请求,这里我们 用百度翻译为例 我们翻译一个spider,然后我们看请求,可以看到有很多 找到sug这个 可以看到这里的form data,就是post请求体中的内容 然后我们点击preview其实就是 返回的实际内容 然后请求方式用的post 然后我们把上面的信息…

Untiy Json和Xml的序列化和反序列化

Json的序列化和反序列化 1.定义数据类 [Serializable] public class ZoomPoint {// 点名称, 将作为Key被字典存储public string name;// 轴心X坐标public Vector2 pivot Vector2.one / 2;// 放大倍率&#xff0c;小于1是为缩小倍率&#xff0c;小于0是取绝对值&#xff0c;不…

BIGEMAP双端buff助力AEC行业无压力进行AutoCAD作图

工具 Bigemap gis office地图软件 BIGEMAP GIS Office-全能版 Bigemap APP_卫星地图APP_高清卫星地图APP AEC行业&#xff0c;即建筑(Architecture)、工程(Engineering)、施工(Construction)&#xff0c;热衷于引入信息通信技术&#xff0c;不仅活跃于国际舞台&#xff0c;还…

GoFastDFS单节点部署

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

Oracle 开发篇+Java通过HiKariCP访问Oracle数据库

标签&#xff1a;HikariCP、数据库连接池、JDBC连接池、释义&#xff1a;HikariCP 是一个高性能的 JDBC 连接池组件&#xff0c;号称性能最好的后起之秀&#xff0c;是一个基于BoneCP做了不少的改进和优化的高性能JDBC连接池。 ★ Java代码 import java.sql.Connection; impor…

【数学建模】--主成分分析

本讲将介绍主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;&#xff0c;主成分分析是一种降维算法&#xff0c;它能将多个指标转换为少数几个主成分&#xff0c;这些主成分是原始变量的线性组合&#xff0c;且彼此之间互不相关&#xff0c;其能…