当前位置: 首页 > news >正文

Spring Security之认证

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
Spring Security之认证


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 系列文章目录
  • 前言
  • 一、什么是Spring Security
  • 二、Spring Security之认证
    • 环境准备
    • 数据库认证
      • 自定义认证逻辑
    • PasswordEncoder
    • 自定义登录页面
    • 突破CSRF防护
    • 会话管理
    • 认证成功后的处理
    • 认证失败后的处理
    • 退出登录
    • 退出成功处理器
    • Remember Me
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

当涉及到构建安全的 Web 应用程序时,Spring Security 是一个广受欢迎且功能强大的框架。它提供了一系列的特性和功能,用于保护应用程序免受未经授权的访问。
在这篇博客中,我们将深入探讨 Spring Security 的认证部分。认证是安全体系的第一道防线,它确保只有经过身份验证的用户才能访问受保护的资源。
我们将从 Spring Security 的基础知识开始,了解它的核心概念和组件。然后,我们将逐步介绍如何使用 Spring Security 实现常见的认证方式,如用户名和密码登录。
无论你是 Spring Security 的新手还是有一定经验的开发者,这篇博客都将为你提供一个深入了解 Spring Security 认证的机会。通过掌握这些知识,你将能够构建更安全、可靠的 Web 应用程序。
让我们一起开启 Spring Security 认证之旅,保护我们的应用程序免受未经授权的访问!


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是Spring Security

Spring Security 是一个用于保护 Spring 应用程序安全性的框架。它提供了一套全面的安全特性,可以帮助开发人员轻松地构建安全的应用程序。Spring Security 的核心目标是提供一种易于使用、灵活且强大的方式来保护应用程序的安全性。
Spring Security 的主要功能包括身份验证、授权、密码加密、跨域安全性等。它支持多种认证方式,如基本认证、摘要认证、JWT 认证等。同时,Spring Security 还提供了强大的授权功能,允许开发人员根据用户角色和权限来限制对特定资源的访问。
总的来说,Spring Security 是一个非常有用的框架,可以帮助开发人员轻松地构建安全的应用程序。

二、Spring Security之认证

认证就是判断用户身份是否合法,如果合法就可以继续访问,不合法就拒绝访问

环境准备

1.准备一个名为mysecurity的Mysql数据库
2.创建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>
<!-- 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>

3.为SpringBoot项目编写配置文件

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.Driverurl: jdbc:mysql:///mysecurity?serverTimezone=UTCusername: rootpassword: root

4.在template文件夹编写项目主页面main.html

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>主页面</title>
</head>
<body>
<h1>主页面</h1>
</body>
</html>

5.编写访问页面控制器

@Controller
public class PageController {@RequestMapping("/{page}")public String showPage(@PathVariable String page){return page;}
}

数据库认证

在实际的项目中,用户通过输入用户名和密码,待验证通过后即登录成功,而用户信息大多保存在数据库中。而用户身份验证的这个过程,我们称之为认证逻辑。
1.准备数据库数据,用户信息数据都是保存在该数据库中

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, 'baizhan', 'baizhan', '13812345678');
INSERT INTO `users` VALUES (2, 'sxt', 'sxt', '13812345678');

2.编写用户实体类

@Data
public class Users {private Integer id;private String username;private String password;private String phone;
}

3.编写dao接口

public interface UsersMapper extends BaseMapper<Users> {
}

4.在 SpringBoot启动类中添加 @MapperScan 注解,扫描Mapper文件夹

@SpringBootApplication
@MapperScan("com.itbaizhan.myspringsecurity.mapper")
public class MysecurityApplication {public static void main(String[] args) {SpringApplication.run(MysecurityApplication.class, args);}
}

自定义认证逻辑

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

5.创建UserDetailsService的实现类,编写自定义认证逻辑

@Service
public class MyUserDetailsService implements UserDetailsService {@Autowiredprivate UsersMapper usersMapper;// 自定义认证逻辑@Overridepublic 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;}
}

PasswordEncoder

在实际的项目开发中,我们往数据库的密码不会是明文密码,而是经过我们加密后的密码。当用户传入的明文密码后,SpringSecurity使用密码解析器将明文密码加密成密文密码,然后再将数据库中的密文密码进行比对,匹配成功则通过,反之不通过。

创建SecurityConfig配置类,添加SpringSecurity密码解析器(PasswordEncoder)

// Security配置类
@Configuration
public class SecurityConfig {//密码编码器@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

自定义登录页面

SpringSecurity给我们提供了登录界面,但是再实际的项目中,登录页面都是用的自己的,这样更能突出项目特色,所以我们要自定义登录界面。
1.编写登录界面
2.在Spring Security配置类自定义登录页面

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{//Spring Security配置@Overrideprotected 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();}@Overridepublic void configure(WebSecurity web) throws Exception {// 静态资源放行web.ignoring().antMatchers("/css/**");}
}

突破CSRF防护

CSRF:跨站请求伪造,通过伪造用户请求访问受信任的站点从而进行非法请求访问,是一种攻击手段。SpringSecurity默认开启CSRF防护,这就限制了除了GET请求以外的大多数请求。我们可以通过关闭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>

会话管理

SpringSecurity提供了会话管理功能,它将用户信息保存再会话中,我们可以通过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();}
}

认证成功后的处理

如果在认证成功后,需要处理一些自定义的逻辑,可以使用登陆成功处理器。
1.自定义登录成功处理器

public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic 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");}
}

2.配置登录成功处理器

http.formLogin() // 使用表单登录.loginPage("/login.html") // 自定义登录页面.usernameParameter("username") // 表单中的用户名项.passwordParameter("password") // 表单中的密码项.loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法//         .successForwardUrl("/main")  //登录成功后跳转的路径.successHandler(new MyLoginSuccessHandler()) //登录成功处理器.failureForwardUrl("/fail"); //登录失败后跳转的路径

认证失败后的处理

如果在认证成功后,需要处理一些自定义的逻辑,可以使用登陆失败处理器。
1.自定义登录失败处理器

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

2.配置登录失败处理器

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(); //其余所有请求都需要认证

退出登录

当用户退出后,需要清楚认证状态、销毁HttpSession对象,跳转登录界面

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

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

2.在网页中添加退出登录超链接

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

退出成功处理器

我们也可以自定义退出成功处理器,在退出后清理一些数据,写法如下:

1.自定义退出成功处理器

public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {System.out.println("清除一些数据...");response.sendRedirect("/login.html");}
}

2.配置退出成功处理器

// 退出登录配置
http.logout().logoutUrl("/logout") // 退出登录路径//         .logoutSuccessUrl("/login.html") // 退出登录后跳转的路径.clearAuthentication(true) //清除认证状态,默认为true.invalidateHttpSession(true) // 销毁HttpSession对象,默认为 true.logoutSuccessHandler(new MyLogoutSuccessHandler()); //自定义退出成功处理器

Remember Me

SpringSecurity提供了“记住我”功能,当使用"记住我"功能登陆后,SpringSecurity会生成一个令牌,令牌一方面保存在数据库里,另一方面生成一个叫remember-me的Cookie保存到客户端。之后客户端访问项目时自动携带令牌,不登录即可完成认证。

1.编写“记住我”配置类

@Configuration
public class RememberMeConfig {@Autowiredprivate DataSource dataSource;// 令牌Repository@Beanpublic PersistentTokenRepository getPersistentTokenRepository() {// 为Spring Security自带的令牌控制器设置数据源JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();jdbcTokenRepositoryImpl.setDataSource(dataSource);//自动建表,第一次启动时需要,第二次启动时注释掉
//     jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);return jdbcTokenRepositoryImpl;}
}

2.修改Security配置类

// 记住我配置
http.rememberMe().userDetailsService(userDetailsService)//登录逻辑交给哪个对象.tokenRepository(repository) //持久层对象.tokenValiditySeconds(30); //保存时间,单位:秒

3.在登录页面添加“记住我”复选框

<form class="form" action="/login" method="post"><input type="text" placeholder="用户名" name="username"><input type="password" placeholder="密码" name="password"><input type="checkbox" name="remember-me" value="true"/>记住我</br><button type="submit">登录</button>
</form>

总结

提示:这里对文章进行总结:

总的来说,Spring Security 为我们提供了一个强大而灵活的框架来保护应用程序的安全性。通过理解和应用所学的知识,我们可以构建更安全、可靠的 Web 应用程序。
希望这篇博客对你有所帮助,让你对 Spring Security 的认证有了更深入的了解。如果你有任何进一步的问题或想要深入探讨其他安全相关主题,请随时留言!

相关文章:

Spring Security之认证

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 Spring Security之认证 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是Spring…...

智能语音机器人NXCallbot

受出海公司业务全球化的影响&#xff0c;智能客服逐渐从便捷应用变为市场刚需。新基建七大领域中&#xff0c;人工智能及场景应用的基础建设是最核心的领域&#xff0c;而智能客服作为商业化实际应用的核心场景之一&#xff0c;能提升企业运营效率&#xff0c;为行业客户赋能。…...

Vue 3中toRaw和markRaw的使用

Vue 3的响应性系统 在Vue 3中&#xff0c;响应性系统是构建动态Web应用程序的关键部分。Vue使用响应性系统来跟踪依赖关系&#xff0c;使数据更改能够自动更新视图。这使得Vue应用程序在数据变化时能够高效地更新DOM。Vue 3引入了新的Proxy对象来替代Vue 2中的Object.definePro…...

移动神器RAX3000M路由器不刷固件变身家庭云之三:外网访问家庭云

本系列文章&#xff1a; 移动神器RAX3000M路由器变身家庭云之一&#xff1a;开通SSH&#xff0c;安装新软件包 移动神器RAX3000M路由器变身家庭云之二&#xff1a;安装vsftpd 移动神器RAX3000M路由器变身家庭云之三&#xff1a;外网访问家庭云 移动神器RAX3000M路由器变身家庭云…...

基于多反应堆的高并发服务器【C/C++/Reactor】(中)线程池的启动和从线程池中取出一个反应堆实例

一、线程池的启动 &#xff08;主线程&#xff09; // 启动线程池 &#xff08;主线程&#xff09; void threadPoolRun(struct ThreadPool* pool) {/*线程池被创建出来之后&#xff0c;接下来就需要让线程池运行起来&#xff0c;其实就是让线程池里的若干个子线程运行起来*//…...

go语言gin框架的基本使用

1.首先在linux环境上安装go环境&#xff0c;这个网上搜搜就行 2.初始化一个go mod&#xff0c;网上搜搜怎么初始化 3.下面go代码的网址和端口绑定自己本机的就行 4.与另一篇CSDN一起食用&#xff0c;效果更好哟---> libcurl的get、post的使用-CSDN博客 package mainimpo…...

TypeScript 从入门到进阶之基础篇(六) 类型(断言 、推论、别名)| 联合类型 | 交叉类型

系列文章目录 TypeScript 从入门到进阶系列 TypeScript 从入门到进阶之基础篇(一) ts基础类型篇TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇TypeScript 从入门到进阶之基础篇(三) 元组类型篇TypeScript 从入门到进阶之基础篇(四) symbol类型篇TypeScript 从入门到进阶…...

Linux操作系统基础(14):文件管理-文件属性命令

1. 查看文件属性 stat命令用于显示文件的详细信息&#xff0c;包括文件的权限、所有者、大小、修改时间等。 #1.显示文件信息 stat file.txt#2.显示文件系统状态 stat -f file.txt#3.显示以时间戳的形式文件信息 stat -t file.txt2. 修改文件时间戳 touch命令用于创建新的空…...

metaSPAdes,megahit,IDBA-UB:宏基因组装软件安装与使用

metaSPAdes,megahit,IDBA-UB是目前比较主流的宏基因组组装软件 metaSPAdes安装 GitHub - ablab/spades: SPAdes Genome Assembler #3.15.5的预编译版貌似有问题&#xff0c;使用源码安装试试 wget http://cab.spbu.ru/files/release3.15.5/SPAdes-3.15.5.tar.gz tar -xzf SP…...

Apache、MySQL、PHP编译安装LAMP环境

1. 请简要介绍一下LAMP环境。 LAMP环境是一个在Linux操作系统上搭建的服务器环境组合&#xff0c;由Apache、MySQL、PHP三种软件构成。这种环境是开源的&#xff0c;跨平台的&#xff0c;并且由于各组件经常一起使用&#xff0c;因此具有高度的兼容性。 其中&#xff0c;Apac…...

L1-087:机工士姆斯塔迪奥

题目描述 在 MMORPG《最终幻想14》的副本“乐欲之所瓯博讷修道院”里&#xff0c;BOSS 机工士姆斯塔迪奥将会接受玩家的挑战。 你需要处理这个副本其中的一个机制&#xff1a;NM 大小的地图被拆分为了 NM 个 11 的格子&#xff0c;BOSS 会选择若干行或/及若干列释放技能&#x…...

如何做一个炫酷的Github个人简介(3DContribution)

文章目录 前言3D-Contrib第一步第二步第三步第四步第五步第六步 前言 最近放假了&#xff0c;毕设目前也不太想做&#xff0c;先搞一点小玩意玩玩&#xff0c;让自己的github看起来好看点。也顺便学学这个action是怎么个事。 3D-Contrib 先给大家看一下效果 我的个人主页&am…...

基于单片机的护理床控制器设计

一、摘要 随着科技的不断发展&#xff0c;人们对生活质量的要求越来越高&#xff0c;特别是在医疗保健领域。护理床作为医院病房中常见的设备&#xff0c;其功能和性能直接影响到患者的康复进程。本文主要介绍了一种基于单片机的护理床控制器设计&#xff0c;该控制器可以实现…...

《3D数学基础-图形和游戏开发》阅读笔记 | 3D数学基础 (学习中 1.6更新)

文章目录 3D数学基础矢量/向量什么是向量点与矢量的关系 向量基础运算 向量加法向量基础运算 数乘 线性组合 - 坐标系的基如果选择不同的基向量会怎么样&#xff1f;- 张成(Span)的空间三维向量的张成空间线性相关与线性相关 矩阵与线性变换矩阵-几何意义线性变换矩阵乘法与线性…...

解锁测试性能瓶颈:深度探讨JMeter分布式性能测试!

在做后端服务器性能测试中&#xff0c;我们会经常听到分布式。但你是否了解分布式呢&#xff1f;今天&#xff0c;我们就来给大家讲讲&#xff0c;在企业实战中&#xff0c;如何使用分布式进行性能测试&#xff0c;实战过程中&#xff0c;又有哪些地方要特别注意&#xff1f; 0…...

SiC电机控制器(逆变器)发展概况及技术方向

SiC电机控制器&#xff08;逆变器&#xff09;发展概况及技术方向 1.概述2.电动汽车动力系统设计趋势3.栅极驱动器和驱动电源配置4.结论 tips&#xff1a;资料来自网上搜集&#xff0c;仅供学习使用。 1.概述 2022年到2023年&#xff0c;第三代半导体碳化硅被推上了新的热潮。…...

useContext

可以跨组件传值 其实主要的就是三步 1、const xxx React.createContext();创建一个context 2、<xxx.Provider value{{ num, setNum }}>父组件设置要传递的值 3、const { num, setNum } React.useContext(xxx);子组件下使用 特点&#xff1a; 1、可以有多个xxx.Pr…...

Java数据结构:1. 数据结构前置知识

文章目录 一、初识数据结构二、初识集合框架1. 什么是集合框架2. 集合框架的重要性3. 背后所涉及的数据结构以及算法 三、时间复杂度空间复杂度1. 算法效率2. 时间复杂度&#xff08;1&#xff09;概念&#xff08;2&#xff09;大O的渐进表示法&#xff08;3&#xff09;推导大…...

Vue中使用Element UI的Table组件实现嵌套表格(最简单示例)

以下是一个简单的示例代码&#xff0c;演示如何在Vue中使用Element UI的Table组件实现嵌套表格&#xff1a; html <template><div><el-table :data"tableData" style"width: 100%"><el-table-column prop"name" label&quo…...

如何使用RESTful API构建 web 应用程序

RESTful API 是一种设计风格&#xff0c;用于构建可扩展、灵活和可维护的 web 应用程序。它是一种基于 HTTP 协议的架构风格&#xff0c;旨在提供一组规范和约束&#xff0c;以便客户端和服务器之间的通信更加简单和可预测。 RESTful API 通过使用 HTTP 动词来定义资源的操作&…...

开启Android学习之旅-4-Android集成FontAwesome

FontAwesome 是一个非常标准、统一风格的图标库。产品经理在原型中应用了很多图标都是FontAwesome。正常流程是 UI 需要再手工绘制或在 iconfont 或 iconpark 网站挨个找&#xff0c;如果在 Android 直接使用不是省了一步&#xff08;注意版权问题&#xff0c;使用免费版&#…...

Qt——TCP UDP网络编程

目录 前言正文一、TCP二、UDP1、基本流程2、必备知识 三、代码层级1、UDP服务端 END、总结的知识与问题1、如何获取QByteArray中某一字节的数据&#xff0c;并将其转为十进制&#xff1f;2、如何以本年本月本日为基础&#xff0c;获取时间戳&#xff0c;而不以1970为基础&#…...

有什么安全处理方案可以有效防护恶意爬虫

常见的爬虫 有百度爬虫、谷歌爬虫、必应爬虫等搜索引擎类爬虫&#xff0c;此类爬虫经常被企业用于提高站点在搜索引擎内的自然排名&#xff0c;使得站点在各大搜索引擎中的排名能够提高&#xff0c;进一步通过搜索引擎来进行引流为企业增加业务流量。 恶意爬虫与合法、合规的搜…...

Flutter3.X基础入门教程(2024完整版)

Flutter介绍&#xff1a; Flutter是谷歌公司开发的一款开源、免费的UI框架&#xff0c;可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。 目前Flutter已经支持 iOS、Android、Web、Windows、macOS、Linux的跨平台开发。 教程所讲内容支持…...

GEE——土地利用分类种两个矢量集合中不同列进行相减的方式(利用join进行连接处理)

问题: 我有两个具有相同 ID 的特征集,我想从第二个特征集中减去第一个特征集的表格单元格。 我使用了这个函数,但它计算的是表 1 中第一个元素与表 2 中其他元素的减法。 我想逐个单元格计算减法。第一个表格中 id 为 1 的单元格减去第二个表格中 id 为 1 的单元格,2x2、…...

mnn-llm: 大语言模型端侧CPU推理优化

在大语言模型(LLM)端侧部署上&#xff0c;基于 MNN 实现的 mnn-llm 项目已经展现出业界领先的性能&#xff0c;特别是在 ARM 架构的 CPU 上。目前利用 mnn-llm 的推理能力&#xff0c;qwen-1.8b在mnn-llm的驱动下能够在移动端达到端侧实时会话的能力&#xff0c;能够在较低内存…...

Freemarker实现Html全站静态化

全站静态化 在大型网站中&#xff0c;比如主流电商商品页&#xff0c;访问者看到的页面基本上是静态页面。为什么都要把页面静态化呢&#xff1f;其实把页面静态化&#xff0c;好处有很多。例如&#xff1a;访问速度快&#xff0c;更有利于搜索引擎收录等。 目前主流的静态化…...

16.顺子日期(14)

题目 public class Main {public static boolean isLegal(String date) {int l 0;int n date.length();while(l<(n-3)) {int t1 (int)Integer.valueOf(date.substring(l,l1));int t2 (int)Integer.valueOf(date.substring(l1,l2));int t3 (int)Integer.valueOf(date.s…...

《动手学深度学习》学习笔记 第5章 深度学习计算

本系列为《动手学深度学习》学习笔记 书籍链接&#xff1a;动手学深度学习 笔记是从第四章开始&#xff0c;前面三章为基础知道&#xff0c;有需要的可以自己去看看 关于本系列笔记&#xff1a; 书里为了让读者更好的理解&#xff0c;有大篇幅的描述性的文字&#xff0c;内容很…...

【Redis】非关系型数据库之Redis的介绍及安装配置

目录 前言 一、关系型数据库与非关系型数据库 1.1关系型数据库 1.2非关系型数据库 1.3两者的区别 1.4非关系型数据库产生的背景 1.5总结 二、Redis介绍 2.1Redis是什么 2.2Redis的优点 2.3Redis的使用场景 2.4那些数据适合放在缓存中 2.5Redis为什么那么快&#xf…...

建设工程业绩查询网站/百度收录技术

<?php //建立连接对象 try {$pdo new PDO(mysql:hostlocalhost;dbnametest,testuser,pass);$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //setAttribute PDO对象的方法&#xff0c;PDO&#xff1a;&#xff1a;表示这些变量是我们所使用的PDO的一…...

长春网站制作长春万网/app下载免费安装

首先我们得在github上创建一个仓库。 填好仓库名称、描述&#xff0c;然后提交就可以了。 在本地安装好Git&#xff0c;俺使用的是bash. 首先配置一下用户名和邮箱~ git config --global user.name "此处为你的github用户名" git config --global user.email &quo…...

网站建设优化重庆/苏州做网站的专业公司

在优化程序的时候&#xff0c;首先需要找出程序性能的瓶颈在哪里&#xff0c;然后针对该瓶颈进行优化。 gprof就是一个这样的剖析程序。它会确定程序中每个函数花费了多少CPU时间。另外&#xff0c;它还计算每个函数被调用的次数。 下面是简单的使用&#xff1a; 1&#xff1a;…...

广东深圳疫情风险等级/优化营商环境指什么

一次应用提供的服务化接口收到报警大量超时,报404.赶忙着手处理: &#xff11;)查看监控报表的cpu load ,jvm gc情况,jvm内存,io都正常,如果没有做监控可以手工到服务器上命令查看 &#xff12;)检查网络包括http响应及tcp网络响应请求情况均正常 &#xff13;)登陆服务器…...

乐清开发网站公司/seo优化外包顾问

为什么要用统一配置&#xff1f; 我们做项目时用到的配置比如数据库配置等...我们都是写死在项目里面&#xff0c;如果需要更改&#xff0c;那么也是的修改配置文件然后再投产上去&#xff0c;那么问题来了&#xff0c;如果做集群的呢&#xff0c;有100台机器&#xff0c;这时…...

计算机网站建设 是什么意思/seo整站优化吧

2019独角兽企业重金招聘Python工程师标准>>> NanoStation M2/5 配置使用指南 Ubiquiti产品及AirOS固件 Windows XP 本配置手册适用于NanoStation M2/M5。请确保NanoStation M2/M5 (以下简称NSM 2 / 5)已通过网线连接到您的计算机网卡&#xff0c;并同时通过POE电源提…...