【SpringBoot】之Security进阶使用(登陆授权)

 🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《SpringBoot开发之Security系列》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁


前言

        在上一期的博客中我们博客分享了Security的相关登陆验证的数据获取以及记住我复选框功能、还有CSRF防御等等。今天给大家带来的是基于上一期的博客分享,是对上一期博客的完善功能以及扩展,上期博客完成的是Security联合数据库登陆验证,以及密码加码、网页生成cookie存储用户信息,最后做了一个csrf接口防御。本期博客带来的是用户登陆后的权限管理以及分配。

一、用户权限集成

1. 代码调整

        在上一期博客中我们的接口实现类实现两个接口类,这种写法是不规格的,因此我们要把一个实现类移出到目录上。

 MyUserDetailsService.java

package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.User;
import com.yx.security.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));return user;}}

配置类调整

         我们之前是跳转页面,现在我们模拟前后端分离,从后台发送数据到前台上用于判断跳转页面。

        我们要想传说数据到前台需要我们借助下面两个工具类,这两个类的代码在之前的博客文章中有,有需要的请翻阅之前的博客文章。 

 

        配置类进行对应的编写

         然后我们再重新运行启动项目

        上述就是我们重新登陆后返回的用户信息。

2. 权限设置

MyUserDetailsService.java
package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.*;
import com.yx.security.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.stream.Collectors;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;
//    实例化实体接口类
//    用户角色接口@Autowiredprivate IUserRoleService userRoleService;
//   角色接口@Autowiredprivate IRoleService roleService;
//    角色权限接口@Autowiredprivate IRoleModuleService roleModuleService;
//    权限接口类@Autowiredprivate IModuleService moduleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));
//        判断是否存在用户if (user == null) {//不存在throw new UsernameNotFoundException("用户名不存在");}
//        先查询用户的身份根据用户的id,获取身份id
//        map遍历对象并且返回新的数据放到一个新的流中
//        collectors.toList()将新的流转换成list集合List<Integer> role_ids = userRoleService.list(new QueryWrapper<UserRole>().eq("user_id", user.getId())).stream().map(UserRole::getRoleId).collect(Collectors.toList());
//        根据身份id查询角色信息的名字字段List<String> roles = roleService.list(new QueryWrapper<Role>().in("role_id", role_ids)).stream().map(Role::getRoleName).collect(Collectors.toList());
//        根据身份id具备的权限idList<Integer> module_ids = roleModuleService.list(new QueryWrapper<RoleModule>().in("role_id", role_ids)).stream().map(RoleModule::getModuleId).collect(Collectors.toList());
//      根据权限id对应的权限List<String> modules = moduleService.list(new QueryWrapper<Module>().in("id", module_ids)).stream().map(Module::getUrl).collect(Collectors.toList());
//        拼接身份及权限roles.addAll(modules);
//        遍历集合获取信息生成新的集合List<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
//        将该集合添加到用户实体对象中的权限属性中user.setAuthorities(authorities);return user;}}

        我们现在去登陆测试一下

          控制台也会显示对应的错误提示

         如下图所示我们在该位置标记端点进行运行测试

        解决的方案有两种,一种是对其数据库中的空值对其进行填写补充;另一种方法就是在后台对其进行空处理。 下面是在后端进行的空处理

         在配置类中加上一个注解 

         给指定的接口方法设置的权限。 

         下面是完整的代码

 IndexController.java
package com.yx.security.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class IndexController {@RequestMapping("/")public String toLogin(){return "login";}@RequestMapping("/index")public String toIndex(){return "accessDenied";}@ResponseBody@RequestMapping("/oreder_add")@PreAuthorize("hasAuthority('order:manager:add')")public String order_add(){return "订单新增";}@ResponseBody@RequestMapping("/book_add")@PreAuthorize("hasAuthority('book:manager:add')")public String book_add(){return "书籍新增";}}
MyUserDetailsService.java
package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.*;
import com.yx.security.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;
//    实例化实体接口类
//    用户角色接口@Autowiredprivate IUserRoleService userRoleService;
//   角色接口@Autowiredprivate IRoleService roleService;
//    角色权限接口@Autowiredprivate IRoleModuleService roleModuleService;
//    权限接口类@Autowiredprivate IModuleService moduleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));
//        判断是否存在用户if (user == null) {//不存在throw new UsernameNotFoundException("用户名不存在");}
//        先查询用户的身份根据用户的id,获取身份id
//        map遍历对象并且返回新的数据放到一个新的流中
//        collectors.toList()将新的流转换成list集合
//        filter过滤器过滤掉nullList<Integer> role_ids = userRoleService.list(new QueryWrapper<UserRole>().eq("user_id", user.getId())).stream().map(UserRole::getRoleId).collect(Collectors.toList());
//        根据身份id查询角色信息的名字字段List<String> roles = roleService.list(new QueryWrapper<Role>().in("role_id", role_ids)).stream().map(Role::getRoleName).collect(Collectors.toList());
//        根据身份id具备的权限idList<Integer> module_ids = roleModuleService.list(new QueryWrapper<RoleModule>().in("role_id", role_ids)).stream().map(RoleModule::getModuleId).collect(Collectors.toList());
//      根据权限id对应的权限List<String> modules = moduleService.list(new QueryWrapper<Module>().in("id", module_ids)).stream().map(Module::getUrl).filter(Objects::nonNull).collect(Collectors.toList());
//        拼接身份及权限roles.addAll(modules);
//        遍历集合获取信息生成新的集合List<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
//        将该集合添加到用户实体对象中的权限属性中user.setAuthorities(authorities);return user;}}
 WebSecurityConfig.java
package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.configuration.EnableWebSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.sql.DataSource;@Configuration
//开启SpringSecurity的默认行为
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {//    引入密码加密类@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//        实例化接口实现类
//        @Autowired
//        private UserServiceImpl userService;@Autowiredprivate MyUserDetailsService userDetailsService;//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;/*** 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)* @param* @return* @throws Exception*/@Beanpublic AuthenticationManager authenticationManager() throws Exception {//创建DaoAuthenticationProviderDaoAuthenticationProvider provider=new DaoAuthenticationProvider();//设置userDetailsService,基于数据库方式进行身份认证provider.setUserDetailsService(userDetailsService);//配置密码编码器provider.setPasswordEncoder(passwordEncoder());return new ProviderManager(provider);}//    实例化数据源@Autowiredprivate DataSource dataSource;/*** 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置*/@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 设置为true要保障数据库该表不存在,不然会报异常哦// 所以第二次打开服务器应用程序的时候得把它设为falsetokenRepository.setCreateTableOnStartup(false);return tokenRepository;}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{http.authorizeRequests()// 开放接口访问权限,不需要登录就可以访问.antMatchers("/").permitAll()
//                admin开头的路径全要只能由管理员进入
//                  .antMatchers("/admin/**").hasRole("ADMIN")// 其余所有请求全部需要登陆才能访问.anyRequest().authenticated().and().formLogin()
//                 设置登录页面的Url.loginPage("/toLogin")
//                 设置处理登陆请求的接口.loginProcessingUrl("/userLogin")
//                 设置用户名参数名与页面的一致.loginProcessingUrl("/userLogin").usernameParameter("username").passwordParameter("password")
//                 成功处理器.successHandler((req, resp, auth)->{
//                     resp.sendRedirect("/index");objectMapper.writeValue(resp.getOutputStream(),auth.getPrincipal());})
//                 设置登录失败跳转页面.failureHandler((req, resp, ex) -> {
//                     设置错误消息req.setAttribute("msg", ex.getMessage());
//                                          跳转到登录页面req.getRequestDispatcher("/").forward(req, resp);}).and()
//                 处理异常跳转其他页面.exceptionHandling().accessDeniedPage("/noAccess").and().logout()// 设置安全退出的URL路径.logoutUrl("/logout")// 设置退出成功后跳转的路径.logoutSuccessUrl("/toLogin").and().rememberMe()// 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。//.rememberMeParameter("remember-me")// 指定 rememberMe 的有效期,单位为秒,默认2周。.tokenValiditySeconds(30)// 指定 rememberMe 的 cookie 名称。.rememberMeCookieName("remember-me-cookie")// 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。.tokenRepository(persistentTokenRepository())// 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。.userDetailsService(userDetailsService);http.csrf().disable();return http.build();}
}

        运行测试代码

         由上图可知我们使用不同的身份进行登陆时,若该身份没有该权限进行访问一些方法时会出现权限报错。

二、自定义处理器

1. 自定义错误类型

        在JsonResponseStatus中进行自定义

 

2. 修改配置类

 

package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.resp.JsonResponseBody;
import com.yx.security.resp.JsonResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.sql.DataSource;@Configuration
//开启SpringSecurity的默认行为
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {//    引入密码加密类@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//        实例化接口实现类
//        @Autowired
//        private UserServiceImpl userService;@Autowiredprivate MyUserDetailsService userDetailsService;//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;/*** 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)* @param* @return* @throws Exception*/@Beanpublic AuthenticationManager authenticationManager() throws Exception {//创建DaoAuthenticationProviderDaoAuthenticationProvider provider=new DaoAuthenticationProvider();//设置userDetailsService,基于数据库方式进行身份认证provider.setUserDetailsService(userDetailsService);//配置密码编码器provider.setPasswordEncoder(passwordEncoder());return new ProviderManager(provider);}//    实例化数据源@Autowiredprivate DataSource dataSource;/*** 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置*/@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 设置为true要保障数据库该表不存在,不然会报异常哦// 所以第二次打开服务器应用程序的时候得把它设为falsetokenRepository.setCreateTableOnStartup(false);return tokenRepository;}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{http.authorizeRequests()// 开放接口访问权限,不需要登录就可以访问.antMatchers("/").permitAll()
//                admin开头的路径全要只能由管理员进入
//                  .antMatchers("/admin/**").hasRole("ADMIN")// 其余所有请求全部需要登陆才能访问.anyRequest().authenticated().and().formLogin()
//                 设置登录页面的Url.loginPage("/toLogin")
//                 设置处理登陆请求的接口.loginProcessingUrl("/userLogin")
//                 设置用户名参数名与页面的一致.loginProcessingUrl("/userLogin").usernameParameter("username").passwordParameter("password")
//                 成功处理器.successHandler((req, resp, auth)->{
//                     resp.sendRedirect("/index");Object user = auth.getPrincipal();objectMapper.writeValue(resp.getOutputStream(), JsonResponseBody.success(user));})
//                 设置登录失败跳转页面.failureHandler((req, resp, ex) -> {
//                     设置错误消息objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}).and()
//                 处理异常跳转其他页面.exceptionHandling()
//                 .accessDeniedPage("/noAccess")
//                 进入到这里代表权限不足.accessDeniedHandler((req, resp, ex)->{
//                     返回权限不足的提示objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_ACCESS));})//没有认证   用户没有登陆.authenticationEntryPoint((req, resp, ex) -> {objectMapper.writeValue(resp.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}).and().logout()// 设置安全退出的URL路径.logoutUrl("/logout")// 设置退出成功后跳转的路径.logoutSuccessUrl("/toLogin").and().rememberMe()// 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。//.rememberMeParameter("remember-me")// 指定 rememberMe 的有效期,单位为秒,默认2周。.tokenValiditySeconds(30)// 指定 rememberMe 的 cookie 名称。.rememberMeCookieName("remember-me-cookie")// 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。.tokenRepository(persistentTokenRepository())// 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。.userDetailsService(userDetailsService);http.csrf().disable();return http.build();}
}

3. 运行测试

        我们运行时由于某些原因导致的代码问题会提示相应的问题

         如果你的代码后面特别多建议移出来新建一个工具类

 MyAuthenticationFailureHandler.java
package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.resp.JsonResponseBody;
import com.yx.security.resp.JsonResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/24*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
//        设置错误消息objectMapper.writeValue(response.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}
}

        后续可以在MyAuthenticationFailureHandler实现用户登陆次数过多用户禁用的功能


🎉🎉本期的博客分享到此结束🎉🎉

📚📚各位老铁慢慢消化📚📚

🎯🎯下期博客博主会带来新货🎯🎯

🎁三连加关注,阅读不迷路 !🎁

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

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

相关文章

智能优化算法应用:基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.天鹰算法4.实验参数设定5.算法结果6.参考文献7.MA…

如何通过UMC配置外围组件

随着云计算技术的不断发展&#xff0c;在信息化建设模式上云是大势所趋。对于企业而言&#xff0c;已建立的内部集成并不能支撑其快速搭建开发环境、快速部署集群服务&#xff0c;并且动态水平扩展对多组织情况许可费用高昂、没有敏捷快速迭代机制&#xff0c;导致开发完毕就落…

增量式旋转编码器在STM32平台上的应用

背景 旋钮是仪器仪表上一种常见的输入设备&#xff0c;它的内部是一个旋转编码器&#xff0c;知乎上的这篇科普文章对其工作原理做了深入浅出的介绍。 我们公司的功率分析仪的前面板也用到了该类设备&#xff0c;最近前面板的MCU从MSP430切换成了STM32&#xff0c;因此我要将…

Could not resolve com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28.

1、首先进入阿里云maven仓库&#xff0c;在搜索栏输入无法下载的依赖名称&#xff0c;查询现有版本号&#xff0c;可以看到这里有2.9.34。 2、在build.gradle(Project)的buildscript闭包下替换为阿里云maven仓库&#xff1a; maven { url https://www.jitpack.io } maven { u…

基于 ACK One 实现简单的跨云协同,让业务管理更高效

作者&#xff1a;庄宇 本文根据 2023 云栖大会现场分享实录整理 2 年前的云栖大会&#xff0c;我们发布分布式云容器平台 ACK One&#xff0c;随着 2 年的发展&#xff0c;很高兴看到 ACK One 在混合云&#xff0c;分布式云领域帮助到越来越多的客户&#xff0c;今天给大家汇报…

中心性算法归纳

中心性算法不仅是在我所学习的计算机网络当中起很重要的作用&#xff0c;在交通网络、社交网络、信息网络、神经网络当中也有很多的应用例子。今天我在这里总结一下场景的几种中心性算法。 参考文献 Python NetworkX库 偏心中心性&#xff08;Eccentricity Centrality&#x…

银河麒麟v10 rpm安装包 安装mysql 8.35

银河麒麟v10 rpm安装包 安装mysql 8.35 1、卸载mariadb2、下载Mysql安装包3、安装Mysql 8.353.1、安装Mysql 8.353.3、安装后配置 1、卸载mariadb 由于银河麒麟v10系统默认安装了mariadb 会与Mysql相冲突&#xff0c;因此首先需要卸载系统自带的mariadb 查看系统上默认安装的M…

网络安全行业术语

病毒 是在计算机程序中插入的破坏计算机功能或者数据的代码&#xff0c;能影响计算机使用&#xff0c;能自我复制的一组计算机指令或者程序代码。 抓鸡 利用使用大量的程序的漏洞&#xff0c;使用自动化方式获取肉鸡的行为&#xff0c;即设法控制电脑&#xff0c;将其沦为肉…

采用SpringBoot框架+原生HTML、JS前后端分离模式开发和部署的电子病历编辑器源码(电子病历评级4级)

概述&#xff1a; 电子病历是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图表、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的医疗记录,是病历的一种记录形式。 医院通过电子病历以电子化方式记录患者就诊的信息&#xff0c;包括&…

网络协议-BIO实战和NIO编程

网络通信编程基本常识 原生JDK网络编程-BIO 原生JDK网络编程-NIO Buffer 的读写 向 Buffer 中写数据 写数据到 Buffer有两种方式: 1. 读取 Channel写到 Buffer。 2.通过 Buffer 的 put0方法写到 Buffer 里。 从 Channel 写到 Buffer …

力扣经典面试题——搜索二维矩阵(两次二分搜索)

https://leetcode.cn/problems/search-a-2d-matrix/description/?envTypestudy-plan-v2&envIdtop-100-liked 思路&#xff1a;先按行二分&#xff0c;再按列进行二分。即先找到对应的行&#xff0c;再找对应的列。 对于这种判断是否存在某个数&#xff0c;记得while(left…

[JS设计模式]Mixin Pattern

Mixin是一个对象&#xff0c;我们可以使用它来为另一个对象或类添加可重用的功能&#xff0c;而无需使用继承。我们不能单独使用mixins:它们的唯一目的是在没有继承的情况下向对象或类添加功能。 假设对于我们的应用程序&#xff0c;我们需要创建多个狗。然而&#xff0c;我们…

【错误记录/js】保存octet-stream为文件后数据错乱

目录 说在前面场景解决方式其他 说在前面 后端&#xff1a;go、gin浏览器&#xff1a;Microsoft Edge 120.0.2210.77 (正式版本) (64 位) 场景 前端通过点击按钮来下载一些文件&#xff0c;但是文件内容是一些非文件形式存储的二进制数据。 后端代码 r : gin.Default()r.Stat…

MyBatis见解2

5.MyBatis的原始Dao开发-了解 使用Mybatis开发Dao&#xff0c;通常有两个方法&#xff0c;即原始Dao开发方式和Mapper接口代理开发方式。而现在主流的开发方式是接口代理开发方式&#xff0c;这种方式总体上更加简便。我们的课程讲解也主要以接口代理开发方式为主。在第4节已经…

冒泡排序之C++实现

描述 冒泡排序算法是一种简单的排序算法&#xff0c;它通过将相邻的元素进行比较并交换位置来实现排序。冒泡排序的基本思想是&#xff0c;每一轮将未排序部分的最大元素逐个向右移动到已排序部分的最右边&#xff0c;直到所有元素都按照从小到大的顺序排列。 冒泡排序的算法…

阿里云 ARMS 应用监控重磅支持 Java 21

作者&#xff1a;牧思 & 山猎 前言 今年的 9 月 19 日&#xff0c;作为最新的 LTS (Long Term Support) Java 版本&#xff0c;Java 21 正式 GA&#xff0c;带来了不少重量级的更新&#xff0c;详情请参考 The Arrival of Java 21 [ 1] 。虽然目前 Java 11 和 Java 17 都…

前缀和+单调双队列+贪心:LeetCode2945:找到最大非递减数组的长度

本文涉及知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 单调双队列 贪心 题目 给你一个下标从 0 开始的整数数组 nums 。 你可以执行任意次操作。每次操作中&#xff0c;你需要选择一个 子数组 &#xff0c;并将这个子数组用它所…

python脚本 ssh工具 ssh上传文档 选择文档并上传到ssh服务器

此文分享一个python脚本,用于快速的定位、选择文档,并将其上传到指定的ssh服务器。 效果演示 🔥完整演示效果 👇第一步,显然,我们需要选择功能 👇第二步,我们需要定位并选择需要上传的文档 👇第三步,确认我们需要上传文档的ssh服务器 👇第四步,定位、选择…

Qt的简单游戏实现提供完整代码

文章目录 1 项目简介2 项目基本配置2.1 创建项目2.2 添加资源 3 主场景3.1 设置游戏主场景配置3.2 设置背景图片3.3 创建开始按钮3.4 开始按钮跳跃特效实现3.5 创建选择关卡场景3.6 点击开始按钮进入选择关卡场景 4 选择关卡场景4.1场景基本设置4.2 背景设置4.3 创建返回按钮4.…

模式识别与机器学习(十一):Bagging

1.原理 Bagging [Breiman, 1996a] 是井行式集成学习方法最著名的代表.从名字即可看出&#xff0c;它直接基于自助采样法(bootstrap sampling)。给定包含m 个样本的数据集&#xff0c;我们先随机取出一个样本放入采样集中&#xff0c;再把该样本放回初始数据集&#xff0c;使得…