springboot集成springsecurity

转载自:www.javaman.cn

1、整合springsecurity

添加pom.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、springsecurity认证授权流程

img

认证管理

在这里插入图片描述

流程图解读:

1、用户提交用户名、密码被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 过滤器获取到, 封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。

2、然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证 。

3、认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息, 身份信息,细节信息,但密码通常会被移除) Authentication 实例。

4、SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过 SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。 可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它 的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个 List 列表,存放多种认证方式,最终实际的认证工作是由 AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为 DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终 AuthenticationProvider将UserDetails填充至Authentication。

授权管理

在这里插入图片描述

访问资源(即授权管理),访问url时,会通过FilterSecurityInterceptor拦截器拦截,其中会调用SecurityMetadataSource的方法来获取被拦截url所需的全部权限,再调用授权管理器AccessDecisionManager,这个授权管理器会通过spring的全局缓存SecurityContextHolder获取用户的权限信息,还会获取被拦截的url和被拦截url所需的全部权限,然后根据所配的投票策略(有:一票决定,一票否定,少数服从多数等),如果权限足够,则决策通过,返回访问资源,请求放行,否则跳转到403页面、自定义页面。

根据上面的认证授权流程,具体的实现步骤从3-8

1、首先定义一个我们自己的实现类集成SpringSecurity的UserDetailsService,实现loadUserByUsername方法,就是下面的步骤3,当抛出AccessDeniedException时,就要进行处理,也就是步骤4

2、接着编写SpringSecurityConfig配置文件,就是下面的步骤7,需要进行认证成功后的处理,就是下面的步骤5

3、认证失败后,对认证失败进行处理,就是下面的步骤6

5、通过auth.userDetailsService(sysUserService),配置 AuthenticationManagerBuilder 来使用 sysUserService 加载用户的详细信息,并使用密码编码器来处理密码。这样,当应用程序需要验证用户的身份时,它会使用这些配置来检查用户提供的凭据(通常是用户名和密码)是否正确。如果凭据正确,用户将被允许访问受保护的资源;如果凭据不正确,将拒绝访问

6、接下来通过步骤7的安全配置:

定义哪些URL不需要身份验证(如/loginPage和/getImgCode)。
配置登录页面、登录处理URL、成功和失败的处理程序等。
添加一个自定义的验证码过滤器。
配置“记住我”功能。
禁用CSRF保护(通常不推荐这样做,但在这里它被禁用了)。
设置响应头中的X-Frame-Options属性。
配置会话管理,例如定义会话失效时的跳转URL。

3、创建SysUserService集成UserDetailsService

定义一个名为SysUserService的服务类,该类主要用于处理与系统用户相关的业务逻辑:

  1. 服务类定义SysUserService继承了ServiceImpl并实现了UserDetailsService接口,这意味着它提供了与用户详细信息相关的服务。
  2. 依赖注入:使用@Autowired注解注入了多个mapper(数据访问对象)和一个密码编码器。这些mapper可能用于访问数据库中的用户、菜单、用户角色和用户岗位信息。
  3. 根据用户名加载用户信息loadUserByUsername方法根据提供的用户名从数据库中检索用户信息。如果找不到用户,则抛出UsernameNotFoundException异常。
  4. 菜单和角色权限的分配
    • 如果用户是管理员(由ConfigConsts.ADMIN_USER定义),则为其分配所有的菜单和角色。
    • 对于普通用户,根据其关联的角色ID从数据库中检索菜单和角色。如果用户没有分配任何角色,则抛出AccessDeniedException异常。
  5. 创建并返回Spring Security的用户对象:使用从数据库中检索到的用户信息(如用户名、密码等)以及分配的菜单和角色创建一个Spring Security的User对象,并返回。

为Spring Security框架提供用户的详细信息和权限设置,确保用户在系统中的访问和操作都是基于其分配的权限进行的。

package com.ds.blog.system.service;import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ds.blog.system.entity.SysUser;
import com.ds.blog.system.entity.SysUserPost;
import com.ds.blog.system.entity.SysUserRole;
import com.ds.blog.system.entity.dto.ModifyPassDTO;
import com.ds.blog.system.entity.dto.ResetPassDTO;
import com.ds.blog.system.entity.dto.UserParamDTO;
import com.ds.blog.system.mapper.*;
import com.ds.common.constant.ConfigConsts;
import com.ds.common.domain.XmSelectNode;
import com.ds.common.enums.ResultStatus;
import com.ds.core.exception.MyGlobalException;
import com.ds.core.util.CommonUtil;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.thymeleaf.util.ArrayUtils;import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;import static java.util.Optional.ofNullable;@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> implements UserDetailsService {@Autowiredprivate SysUserMapper sysUserMapper;@Autowiredprivate SysMenuMapper sysMenuMapper;@Autowiredprivate SysUserRoleMapper sysUserRoleMapper;@Autowiredprivate SysUserPostMapper sysUserPostMapper;@Autowiredprivate BCryptPasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = sysUserMapper.findByUserName(username);if (ObjectUtil.isNull(user)) {throw new UsernameNotFoundException("用户不存在");}List<String> menuRole;if (ConfigConsts.ADMIN_USER.equals(username)) {menuRole = sysMenuMapper.findMenuRole();} else {String roleIds = user.getRoleIds();if (StringUtils.isBlank(roleIds)) {throw new AccessDeniedException("用户未分配菜单");}Long[] ids = CommonUtil.getId(user.getRoleIds());menuRole = sysMenuMapper.findMenuRoleByRoleIds(ids);}return new User(user.getUserName(), user.getPassWord(), ConfigConsts.SYS_YES.equals(user.getEnabled()),true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", menuRole)));}
}
4、自定义AccessDeniedHandler

在步骤3中抛出 AccessDeniedException(“用户未分配菜单”),我们需要自定义处理器来处理该异常。

这段代码定义了一个名为CustomAccessDeniedHandler的类,该类实现了AccessDeniedHandler接口。这主要是用于Spring Security框架中,当用户尝试访问他们没有权限的资源时,自定义如何处理这种访问被拒绝的情况。

以下是代码的详细解释:

  1. @Component:这是一个Spring的注解,它表示CustomAccessDeniedHandler是一个Spring组件。这意味着Spring会在启动时自动检测、注册并管理这个类的实例。

  2. 实现AccessDeniedHandler接口AccessDeniedHandler是Spring Security中的一个接口,它要求实现一个handle方法。当在Spring Security中发生AccessDeniedException异常时,这个handle方法会被调用。

  3. handle方法

    • 参数

      :此方法有三个参数:

      • HttpServletRequest request:代表HTTP请求,可以用来获取请求相关的信息,如请求头、请求参数等。
      • HttpServletResponse response:代表HTTP响应,可以用来设置响应的状态码、响应头、响应体等。
      • AccessDeniedException e:是触发此处理程序的异常。可以提供有关为什么访问被拒绝的信息。
    • 方法体

      • response.setCharacterEncoding("utf-8"):设置响应的字符编码为UTF-8。
      • response.setContentType("application/json;charset=utf-8"):设置响应的内容类型为JSON,并确保字符编码为UTF-8。
      • response.getWriter().write(new ObjectMapper().writeValueAsString(new MyGlobalException(ResultStatus.TEST_USER_LIMIT))):使用Jackson库的ObjectMapperMyGlobalException对象序列化为JSON字符串,并将其写入响应体。从代码中可以看出,当访问被拒绝时,会返回一个具有特定状态的全局异常信息。

总的来说,这段代码的主要作用是为Spring Security提供一个自定义的访问拒绝处理器,当用户尝试访问他们没有权限的资源时,它会返回一个具有特定状态的JSON格式的错误信息。

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");response.getWriter().write(new ObjectMapper().writeValueAsString(e.getMessage()));}
}
5、自定义AuthenticationSuccessHandler(认证成功处理)

定义一个名为DefaultAuthenticationSuccessHandler的类,该类是Spring Security框架中用于处理成功认证后的逻辑的组件。以下是代码的主要功能点:

  1. @Component:这是一个Spring的注解,表示该类是一个Spring组件,Spring会在启动时自动检测、注册并管理其实例。
  2. @Slf4j:这是Lombok库提供的注解,它为这个类自动生成了一个SLF4J的logger实例,名为log。这允许你在类中方便地记录日志。
  3. 扩展SavedRequestAwareAuthenticationSuccessHandler:该类继承了SavedRequestAwareAuthenticationSuccessHandler,这是Spring Security提供的一个处理器,用于在用户成功认证后重定向他们到最初请求的页面(如果存在的话)。
  4. onAuthenticationSuccess方法:这个方法覆盖了父类中的同名方法。当用户成功认证时,该方法会被调用。在这个方法中,你可以定义成功后想要执行的逻辑。这里的逻辑包括:
    • 记录一个表示成功登录的日志。
    • 设置HTTP响应的字符编码为UTF-8。
    • 设置HTTP响应的内容类型为JSON。
    • 使用响应的PrintWriter对象将一个表示成功的JSON字符串写入响应体,并刷新输出流。

总的来说,这段代码的主要作用是当用户成功认证后,记录一个日志,并向客户端发送一个表示成功的JSON响应。

@Component
@Slf4j
public class DefaultAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {log.info("-----login in success----");response.setCharacterEncoding("utf-8");response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();writer.write(JSON.toJSONString(Result.success()));writer.flush();}
}
6、自定义AuthenticationFailureHandler(认证失败处理)

定义一个名为DefaultAuthenticationFailureHandler的类,该类是Spring Security框架中用于处理认证失败后的逻辑的组件。以下是代码的主要功能点:

  1. @Component:这是一个Spring的注解,表示该类是一个Spring组件,Spring会在启动时自动检测、注册并管理其实例。
  2. @Slf4j:这是Lombok库提供的注解,它为这个类自动生成了一个SLF4J的logger实例,名为log。这允许你在类中方便地记录日志。
  3. 扩展SimpleUrlAuthenticationFailureHandler:该类继承了SimpleUrlAuthenticationFailureHandler,这是Spring Security提供的一个处理器,用于处理认证失败的情况,并默认重定向到一个指定的失败URL。
  4. onAuthenticationFailure方法:这个方法覆盖了父类中的同名方法。当认证失败时,该方法会被调用。在这个方法中,你可以定义认证失败后想要执行的逻辑。这里的逻辑包括:
    • 记录一个表示登录失败的日志,并打印出具体的异常信息。
    • 设置HTTP响应的内容类型为JSON。
    • 设置HTTP响应的字符编码为UTF-8。
    • 使用响应的PrintWriter对象将错误信息写入响应体。
    • 如果异常是BadCredentialsException(通常表示用户名或密码不正确),则返回一个特定的错误消息“用户名或密码错误,请重试。”。
    • 对于其他类型的异常,直接返回异常的错误消息。

总的来说,这段代码的主要作用是当认证失败时,记录一个日志,并根据异常类型向客户端发送一个表示失败的JSON响应,其中包含具体的错误信息。

@Component
@Slf4j
public class DefaultAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {log.info("login in failure : " +  exception.getMessage());response.setContentType("application/json;charset=utf-8");response.setCharacterEncoding("utf-8");PrintWriter writer = response.getWriter();String message;if (exception instanceof BadCredentialsException) {message =  "用户名或密码错误,请重试。";writer.write(JSON.toJSONString(Result.failure(message)));}else{writer.write(JSON.toJSONString(Result.failure(exception.getMessage())));}writer.flush();}
}
7、MySecurityConfig配置

这段代码是一个Spring Security的配置类,用于配置Web应用的安全性。Spring Security是一个功能强大且可定制的身份验证和访问控制框架。

以下是该代码的主要功能点:

  1. @Configuration:这是一个Spring的注解,表示该类是一个配置类,用于定义和注册beans。
  2. @EnableWebSecurity:这个注解告诉Spring Boot启用Spring Security的默认Web安全性。
  3. @EnableGlobalMethodSecurity(prePostEnabled = true):这个注解启用了全局方法安全性,允许你使用注解(如@PreAuthorize、@PostAuthorize等)在方法级别上定义访问控制。
  4. WebSecurityConfigurerAdapter:该类继承了WebSecurityConfigurerAdapter,允许你自定义Spring Security的配置。
  5. configure(AuthenticationManagerBuilder auth):在这个方法中,你可以配置AuthenticationManager,这是处理身份验证逻辑的核心组件。在这里,它配置了一个UserDetailsService和一个PasswordEncoder来处理用户的身份验证。
  6. configure(HttpSecurity http):这个方法用于配置HTTP安全性。其中包括:
    • 定义哪些URL不需要身份验证(如/loginPage/getImgCode)。
    • 配置登录页面、登录处理URL、成功和失败的处理程序等。
    • 添加一个自定义的验证码过滤器。
    • 配置“记住我”功能。
    • 禁用CSRF保护(通常不推荐这样做,但在这里它被禁用了)。
    • 设置响应头中的X-Frame-Options属性。
    • 配置会话管理,例如定义会话失效时的跳转URL。

总的来说,这段代码配置了Spring Security来处理Web应用的安全性,包括身份验证、访问控制、会话管理等。需要注意的是,其中禁用了CSRF保护,这通常是不安全的做法,除非有特定的原因。

package com.ds.core.config;import com.ds.blog.system.service.SysUserService;
import com.ds.core.security.CustomAccessDeniedHandler;
import com.ds.core.security.DefaultAuthenticationFailureHandler;
import com.ds.core.security.DefaultAuthenticationSuccessHandler;
import com.ds.core.security.filter.ValidateCodeFilter;
import net.bytebuddy.asm.Advice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate SysUserService sysUserService;@Autowiredprivate DefaultAuthenticationSuccessHandler defaultAuthenticationSuccessHandler;@Autowiredprivate DefaultAuthenticationFailureHandler defaultAuthenticationFailureHandler;@Autowiredprivate ValidateCodeFilter validateCodeFilter;@Autowiredprivate CustomAccessDeniedHandler accessDeniedHandler;@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(sysUserService).passwordEncoder(passwordEncoder());}@Overridepublic void configure(WebSecurity web) throws Exception {// 不需要权限能访问的资源web.ignoring()// 接口放行.antMatchers("/api/**").antMatchers("/front/**")// 静态资源.antMatchers("/static/**").antMatchers("/favicon.ico");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()// 放过.antMatchers("/loginPage", "/getImgCode").permitAll().antMatchers("/**/*.jpg", "/**/*.png", "/**/*.gif", "/**/*.jpeg").permitAll()// 剩下的所有的地址都是需要在认证状态下才可以访问.anyRequest().authenticated().and()// 过滤登录验证码.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)// 配置登录功能.formLogin().usernameParameter("userName").passwordParameter("passWord")// 指定指定要的登录页面.loginPage("/loginPage")// 处理认证路径的请求.loginProcessingUrl("/login").successHandler(defaultAuthenticationSuccessHandler).failureHandler(defaultAuthenticationFailureHandler).and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()// 登出.logout().invalidateHttpSession(true).deleteCookies("remember-me").logoutUrl("/logout").logoutSuccessUrl("/loginPage").and().rememberMe()// 有效期7天.tokenValiditySeconds(3600 * 24 * 7)// 开启记住我功能.rememberMeParameter("remember-me").and()//禁用csrf.csrf().disable()// header response的X-Frame-Options属性设置为SAMEORIGIN.headers().frameOptions().sameOrigin().and()// 配置session管理.sessionManagement()//session失效默认的跳转地址.invalidSessionUrl("/loginPage");}
}
8、登录界面
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head><title>ds博客</title><div th:replace="common/link::header"></div><link rel="stylesheet" th:href="@{/static/layuiadmin/style/login.css}" media="all">
</head>
<body>
<div class="layadmin-user-login layadmin-user-display-show" id="LAY-user-login" style="display: none;"><div class="layadmin-user-login-main"><div class="layadmin-user-login-box layadmin-user-login-header"><h2>ds博客</h2><p>后台登录</p></div><div class="layadmin-user-login-box layadmin-user-login-body layui-form"><div class="layui-form-item"><label class="layadmin-user-login-icon layui-icon layui-icon-username" for="LAY-user-login-username"></label><input type="text" name="userName" value="test" id="LAY-user-login-username" lay-verify="required" placeholder="用户名" class="layui-input"></div><div class="layui-form-item"><label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LAY-user-login-password"></label><input type="password" name="passWord" value="test" id="LAY-user-login-password" lay-verify="required" placeholder="密码" class="layui-input"></div><div class="layui-form-item"><div class="layui-row"><div class="layui-col-xs7"><label class="layadmin-user-login-icon layui-icon layui-icon-vercode"></label><input type="text" name="code"  lay-verify="required" placeholder="图形验证码" class="layui-input"></div><div class="layui-col-xs5"><div style="margin-left: 10px;"><img id="codeImg" class="layadmin-user-login-codeimg"></div></div></div></div><div class="layui-form-item" style="margin-bottom: 20px;"><input type="checkbox" name="remember-me" lay-skin="primary" title="记住密码"></div><div class="layui-form-item"><button class="layui-btn layui-btn-fluid layui-bg-blue"  lay-submit lay-filter="login">登 录</button></div></div></div><div th:replace="common/script::footer"></div>
<script th:inline="javascript">layui.config({base: '/static/layuiadmin/' //静态资源所在路径}).extend({index: 'lib/index' //主入口模块}).use(['index', 'user'], function(){let $ = layui.$,form = layui.form;// 初始化getImgCode();form.render();//提交form.on('submit(login)', function(obj) {// 打开loadinglet loading = layer.load(0, {shade: false,time: 2 * 1000});// 禁止重复点击按钮$('.layui-btn').attr("disabled",true);//请求登入接口$.ajax({type: 'POST',url:  ctx + '/login',data: obj.field,dataType: 'json',success: function(result) {if (result.code === 200) {layer.msg('登入成功', {icon: 1,time: 1000}, function(){window.location.href = '/';});} else {layer.msg(result.message);// 刷新验证码getImgCode();// 关闭loadinglayer.close(loading);// 开启点击事件$('.layui-btn').attr("disabled", false);}}});});$("#codeImg").on('click', function() {// 添加验证码getImgCode();});$(document).keydown(function (e) {if (e.keyCode === 13) {$('.layui-btn').click();}});// 解决session过期跳转到登录页并跳出iframe框架$(document).ready(function () {if (window != top) {top.location.href = location.href;}});});/*** 获取验证码*/function getImgCode() {let url = ctx + '/getImgCode';let xhr = new XMLHttpRequest();xhr.open('GET', url, true);xhr.responseType = "blob";xhr.onload = function() {if (this.status === 200) {let blob = this.response;document.getElementById("codeImg").src = window.URL.createObjectURL(blob);}}xhr.send();}
</script>
</body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp挽留提示2.0

项目需求&#xff1a;有时候挽留的ui是全屏的&#xff0c;用page-container也可以。后来产品提了个问题&#xff0c;手机侧滑的时候没那么顺畅&#xff08;就是一用侧滑&#xff0c;就显示出来&#xff0c;产品要的方案是如下图&#xff0c;emmm大概是这个意思&#xff09; 后面…

网络协议系列:TCP三次握手,四次挥手的全过程,为什么需要三次握手,四次挥手

TCP三次握手&#xff0c;四次挥手的全过程&#xff0c;为什么需要三次握手&#xff0c;四次挥手 一. TCP三次握手&#xff0c;四次挥手的全过程&#xff0c;为什么需要三次握手&#xff0c;四次挥手前言TCP协议的介绍三次握手三次握手流程&#xff1a;1. A 的 TCP 向 B 发送 连…

爬虫项目实战:利用基于selenium框架的爬虫模板爬取豆瓣电影Top250

&#x1f44b; Hi, I’m 货又星&#x1f440; I’m interested in …&#x1f331; I’m currently learning …&#x1f49e; I’m looking to collaborate on …&#x1f4eb; How to reach me … README 目录&#xff08;持续更新中&#xff09; 各种错误处理、爬虫实战及模…

浏览器插api开发文档

chrome谷歌浏览器开发文档

软著项目推荐 深度学习二维码识别

文章目录 0 前言2 二维码基础概念2.1 二维码介绍2.2 QRCode2.3 QRCode 特点 3 机器视觉二维码识别技术3.1 二维码的识别流程3.2 二维码定位3.3 常用的扫描方法 4 深度学习二维码识别4.1 部分关键代码 5 测试结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天…

Java后端开发——JDBC(万字详解)

Java后端开发——JDBC&#xff08;万字详解&#xff09; 今日目标 掌握JDBC的的CRUD理解JDBC中各个对象的作用掌握Druid的使用 1&#xff0c;JDBC概述 在开发中我们使用的是java语言&#xff0c;那么势必要通过java语言操作数据库中的数据。这就是接下来要学习的JDBC。 1.1 …

GitHub桌面版

GitHub桌面版 一、GitHub 桌面版二、clone 仓库三、更新仓库 一、GitHub 桌面版 二、clone 仓库 三、更新仓库

Spring面向切面编程(AOP);Spring控制反转(IOC);解释一下Spring AOP里面的几个名词;Spring 的 IoC支持哪些功能

文章目录 Spring面向切面编程(AOP)什么是AOPSpring AOP and AspectJ AOP 的区别&#xff1f;Spring AOP中的动态代理如何理解 Spring 中的代理&#xff1f;解释一下Spring AOP里面的几个名词Spring在运行时通知对象Spring切面可以应用5种类型的通知&#xff1a;什么是切面 Aspe…

Modbus TCP

Modbus &#xff08;&#x1f446; 百度百科&#xff0c;放心跳转&#xff09; 起源 Modbus 由 Modicon 公司于 1979 年开发&#xff0c;是一种工业现场总线协议标准。 Modbus 通信协议具有多个变种&#xff0c;支持串口&#xff0c;以太网多个版本&#xff0c;其中最著名的…

一种方便、优美的使用Python调用fofa API的方法

免责声明&#xff1a;由于传播或利用此文所提供的信息、技术或方法而造成的任何直接或间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c; 文章作者不为此承担任何责任。 学习网络安全的过程中&#xff0c;绕不开fofa搜索&#xff0c;我的需求是使用fofa获取互联网所…

安防监控视频融合平台EasyCVR定制化页面开发

安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索…

牛客 算法题 【HJ102 字符统计】 golang实现

题目 HJ102 字符统计 golang代码实现 package mainimport ("bufio""fmt""os""sort" )func main() {// str_arry :make([]string, 0)str_map : make(map[rune]int)result_map : make(map[int][]string)scanner : bufio.NewScanner(os…

基于mvc电影院售票预订选座系统php+vue+elementui

本影院售票系统主要包括二大功能模块&#xff0c;管理员功能模块和用户功能模块。 &#xff08;1&#xff09;管理员模块&#xff1a;系统中的核心用户管理员登录后&#xff0c;通过管理员功能来管理后台系统。主要功能有&#xff1a;首页、个人中心、电影类型管理、场次时间管…

GitHub上8个强烈推荐的 Python 项目

文章目录 前言1. Manim2. DeepFaceLab3. Airflow4. GPT-25. XSStrike6. 谷歌图片下载7. Gensim8. SocialMapper总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③…

高等数学零基础篇复习笔记

预备章 零基础高等数学入门知识 第一节 集合、运算与关系 第二节 三角函数与反三角函数 三角函数的公式 反三角函数 第三节 常见不等式及数列 划重点 第一章 函数、极限与连续 第一节 函数及函数的初等特性 特殊函数 反函数 函数的初等特性 ①有界性 ②奇偶性 偶函数图像…

谈谈中间件设计的思路

前言 想要设计和真正理解中间件的架构理论和思想。对于开发来说需要具备三个关键的能力 1&#xff1a;基础通用技术的深入理解和运用2&#xff1a;了解和熟悉常见中间件的设计思想&#xff0c;且有自己的感悟,并且能按照自己的理解模仿写一写3&#xff1a;业务的高度理解能力…

京东API接口的接入(京东工业)

在技术交流群&#xff0c;大家有探讨稳定获取京东商品主图、价格、标题&#xff0c;及sku的完整解决方案。这个引起了我技术挑战的兴趣。 目前&#xff0c;自己做了压测&#xff0c;QPS高、出滑块概率极低&#xff0c;API整体稳定&#xff0c;可满足业务场景的性能需求。 公共…

Python - Real-ESRGAN 提升图像、视频清晰度 - 最高可达 4 K

目录 一.引言 二.Real-ESRGAN 理论 1.模型简介 2.经典退化模型 ◆ 退化过程全览 ◆ K - 高斯滤波 ◆ N - 噪声 ◆ ↓r - Resize ◆ jpeg - 压缩 3.高阶退化模型 4.环形和超调伪影 5.网络结构 ◆ ESRGAN 生成器 ◆ U-Net 鉴别器 三.Real-ESRGAN 实战 1.快速体验…

解析javascript数组方法 find 和 filter 有何区别

首先用一个案例可以很直观的看到 find 和 filter 的区别&#xff1b; 相同点&#xff1a; 两者分别可以接受三个参数&#xff1a;当前元素、当前索引、整个数组&#xff1b;两者都可以用来查找数组中符合条件的元素&#xff1b; 不同点&#xff1a; find&#xff1a; 用于查…

TypeScript 学习笔记 第二部分 webpack 创建typescript项目

【视频链接】尚硅谷TypeScript教程&#xff08;李立超老师TS新课&#xff09; 创建webpack 项目 IDE&#xff1a;webstorm 新建一个空的项目运行npm init初始化项目目录结构 1. 安装 webpack&#xff1a;构建工具webpack-cli&#xff1a; webpack的命令行工具typescript&am…