Spring Security入门教程:实现自定义用户配置

在上一篇文章中:Spring Security入门教程:利用Spring Security实现安全控制
我们学会了使用Spring Security实现安全控制,学会了他的基础使用,这节课我们来学习一下它的自定义的功能,更深入的了解和使用Spring Security。

登录成功失败和注销

在Spring Security中我们可以自己实现登录成功跟登录失败之后我们系统做的事情。首先我们定义一个登陆失败的类。我们需要实现一个AuthenticationFailureHandler 接口,并且重写他的onAuthenticationFailure方法。

package com.masiyi.springsecuritydemo.handler;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {Map<String, Object> result = new HashMap<String, Object>();result.put("msg", "登录失败: "+exception.getMessage());result.put("status", 500);response.setContentType("application/json;charset=UTF-8");String s = new ObjectMapper().writeValueAsString(result);response.getWriter().println(s);}
}

例如在我们这个上面,我们给要用方返回一个登录失败的提示信息。
之后我们在自定义一个登录成功的处理类。他跟上面的登陆失败的。写法类似,也是实现一个AuthenticationSuccessHandler 接口,在这个方法里面。我们给调用端返回一个登录成功的信息。

package com.masiyi.springsecuritydemo.handler;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {Map<String, Object> result = new HashMap<String, Object>();result.put("msg", "登录成功");result.put("status", 200);response.setContentType("application/json;charset=UTF-8");String s = new ObjectMapper().writeValueAsString(result);response.getWriter().println(s);}
}

当然类似的还有退出成功的处理类

package com.masiyi.springsecuritydemo.handler;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {Map<String, Object> result = new HashMap<String, Object>();result.put("msg", "注销成功");result.put("status", 200);response.setContentType("application/json;charset=UTF-8");String s = new ObjectMapper().writeValueAsString(result);response.getWriter().println(s);}
}

订完这三个自定义的类之后,我们需要给它配置。这样的话,spring security就知道我们需要他做一些什么事情。我们写一个配置类如下。我们刚刚写好的自定义的处理类给他set值进去。这样的话我们再进行一个登录成功,登录失败跟退出操作。他就会执行我们自定义类里面的逻辑。

package com.masiyi.springsecuritydemo.config;import com.masiyi.springsecuritydemo.handler.MyAuthenticationFailureHandler;
import com.masiyi.springsecuritydemo.handler.MyAuthenticationSuccessHandler;
import com.masiyi.springsecuritydemo.handler.MyLogoutSuccessHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeHttpRequests().mvcMatchers("/user").permitAll().anyRequest().authenticated().and().formLogin().successHandler(new MyAuthenticationSuccessHandler()).failureHandler(new MyAuthenticationFailureHandler()).and().logout().logoutSuccessHandler(new MyLogoutSuccessHandler());}
}

获取登录成功的用户信息


@RestController
public class BasicController {@RequestMapping("/auth")public String hello() {//org.springframework.security.web.context.HttpRequestResponseHolder 关键方法Authentication authentication = SecurityContextHolder.getContext().getAuthentication();org.springframework.security.core.userdetails.User principal = (org.springframework.security.core.userdetails.User) authentication.getPrincipal();System.out.println("身份 :"+principal.getUsername());System.out.println("凭证 :"+authentication.getCredentials());System.out.println("权限 :"+authentication.getAuthorities());return "hello security";}}

SecurityContextHolder.getContext() 获取Spring Security的上下文,上下文中存储着登录的用户信息Authentication ,利用SecurityContextHolder.getContext().getAuthentication()即可获取

自定义内存用户

我们在WebSecurityConfigurer里面添加如下代码,之前我们都是在yml文件中配置用户和密码,这样的话我们可以在代码中使用内存中的用户信息

 @Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager= new InMemoryUserDetailsManager();UserDetails u1 = User.withUsername("masiyi").password("{noop}111").roles("USER").build();inMemoryUserDetailsManager.createUser(u1);return inMemoryUserDetailsManager;}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService());}

自定义数据源用户

在实际工作和项目中我们肯定不会和上门一样把用户和密码写死,大部分我们是把用户信息存储在数据库中的,所以我们就需要学习在Spring Security中自定义数据源用户,这里以mysql数据库为例

首先在pom文件中引入以下jar包:

      <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.7</version></dependency>

接着在配置文件中加入你的数据库连接信息:

# datasource
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springsecurity?characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.masiyi.springsecuritydemo.entity

在数据库中执行以下sql以创建对应的数据表

/*Navicat Premium Data TransferSource Server         : localhostSource Server Type    : MySQLSource Server Version : 50738Source Host           : localhost:3306Source Schema         : springsecurityTarget Server Type    : MySQLTarget Server Version : 50738File Encoding         : 65001Date: 20/12/2023 19:47:32
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,`name_zh` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, 'ROLE_product', '商品管理员');
INSERT INTO `role` VALUES (2, 'ROLE_admin', '系统管理员');
INSERT INTO `role` VALUES (3, 'ROLE_user', '用户管理员');-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,`enabled` tinyint(1) DEFAULT NULL,`accountNonExpired` tinyint(1) DEFAULT NULL,`accountNonLocked` tinyint(1) DEFAULT NULL,`credentialsNonExpired` tinyint(1) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'root', '{noop}123', 1, 1, 1, 1);
INSERT INTO `user` VALUES (2, 'admin', '{noop}123', 1, 1, 1, 1);
INSERT INTO `user` VALUES (3, 'blr', '{noop}123', 1, 1, 1, 1);-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (`id` int(11) NOT NULL AUTO_INCREMENT,`uid` int(11) DEFAULT NULL,`rid` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `uid`(`uid`) USING BTREE,INDEX `rid`(`rid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1, 1);
INSERT INTO `user_role` VALUES (2, 1, 2);
INSERT INTO `user_role` VALUES (3, 2, 2);
INSERT INTO `user_role` VALUES (4, 3, 3);SET FOREIGN_KEY_CHECKS = 1;

根据user表新建一个对应的实体类,但是这个类要实现UserDetails 接口

package com.masiyi.springsecuritydemo.entity;import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;public class User implements UserDetails {private Integer id;private String username;private String password;private Boolean enabled;private Boolean accountNonExpired;private Boolean accountNonLocked;private Boolean credentialsNonExpired;private List<Role> roles = new ArrayList<>();@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<GrantedAuthority> grantedAuthorities = new ArrayList<>();roles.forEach(role -> grantedAuthorities.add(new SimpleGrantedAuthority(role.getName())));return grantedAuthorities;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Overridepublic String getUsername() {return username;}@Overridepublic String getPassword() {return password;}@Overridepublic boolean isAccountNonExpired() {return accountNonExpired;}@Overridepublic boolean isAccountNonLocked() {return accountNonLocked;}@Overridepublic boolean isCredentialsNonExpired() {return credentialsNonExpired;}@Overridepublic boolean isEnabled() {return enabled;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public Boolean getEnabled() {return enabled;}public void setEnabled(Boolean enabled) {this.enabled = enabled;}public Boolean getAccountNonExpired() {return accountNonExpired;}public void setAccountNonExpired(Boolean accountNonExpired) {this.accountNonExpired = accountNonExpired;}public Boolean getAccountNonLocked() {return accountNonLocked;}public void setAccountNonLocked(Boolean accountNonLocked) {this.accountNonLocked = accountNonLocked;}public Boolean getCredentialsNonExpired() {return credentialsNonExpired;}public void setCredentialsNonExpired(Boolean credentialsNonExpired) {this.credentialsNonExpired = credentialsNonExpired;}public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}
}

Role 角色类

package com.masiyi.springsecuritydemo.entity;public class Role {private Integer id;private String name;private String nameZh;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNameZh() {return nameZh;}public void setNameZh(String nameZh) {this.nameZh = nameZh;}
}

新建一个xml文件对应user

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.masiyi.springsecuritydemo.dao.UserDao"><!--查询单个--><select id="loadUserByUsername" resultType="User">select id,username,password,enabled,accountNonExpired,accountNonLocked,credentialsNonExpiredfrom userwhere username = #{username}</select><!--查询指定行数据--><select id="getRolesByUid" resultType="Role">select r.id,r.name,r.name_zh nameZhfrom role r,user_role urwhere r.id = ur.ridand ur.uid = #{uid}</select>
</mapper>

UserDao 接口

package com.masiyi.springsecuritydemo.dao;import com.masiyi.springsecuritydemo.entity.Role;
import com.masiyi.springsecuritydemo.entity.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface UserDao {//根据用户名查询用户User loadUserByUsername(String username);//根据用户id查询角色List<Role> getRolesByUid(Integer uid);
}

MyUserDetailService类,实现org.springframework.security.core.userdetails.UserDetailsService接口,重写loadUserByUsername方法。

package com.masiyi.springsecuritydemo.service;import com.masiyi.springsecuritydemo.dao.UserDao;
import com.masiyi.springsecuritydemo.entity.User;
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;
import org.springframework.util.ObjectUtils;@Component
public class MyUserDetailService implements UserDetailsService {private final UserDao userDao;@Autowiredpublic MyUserDetailService(UserDao userDao) {this.userDao = userDao;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userDao.loadUserByUsername(username);if (ObjectUtils.isEmpty(user)) {throw new RuntimeException("用户不存在");}user.setRoles(userDao.getRolesByUid(user.getId()));return user;}
}

在WebSecurityConfigurer类中把

    @Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager= new InMemoryUserDetailsManager();UserDetails u1 = User.withUsername("masiyi").password("{noop}111").roles("USER").build();inMemoryUserDetailsManager.createUser(u1);return inMemoryUserDetailsManager;}

注释掉,用下面的配置

    @Autowiredprivate MyUserDetailService myUserDetailService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);}

这样,就可以读取自定义的用户了,即自定义数据源用户。

注册,加密密码,登录解密密码

在上面我们是直接初始化用户的,我们并没有添加用户的功能,但是在实际项目当中,肯定要有注册的功能,所以我们给前端写一个注册的方法

package com.masiyi.springsecuritydemo.controller;import com.masiyi.springsecuritydemo.service.MyUserDetailService;
import com.masiyi.springsecuritydemo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author masiyi* @Date 2023/12/20* @PackageName:com.masiyi.springsecuritydemo.controller* @ClassName: UserController* @Description: TODO* @Version 1.0*/
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate MyUserDetailService myUserDetailService;@PostMapping("/register")public Boolean register(@RequestBody User userInfo){return myUserDetailService.insertUser(userInfo);}}

MyUserDetailService 类中我们的insertUser方法如下


import com.masiyi.springsecuritydemo.dao.UserDao;
import com.masiyi.springsecuritydemo.entity.User;
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.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;@Component
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate  UserDao userDao;@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userDao.loadUserByUsername(username);if (ObjectUtils.isEmpty(user)) {throw new RuntimeException("用户不存在");}user.setRoles(userDao.getRolesByUid(user.getId()));return user;}public Boolean insertUser(User userInfo) {//登录的时候在 UsernamePasswordAuthenticationFilter里面解密userInfo.setPassword(passwordEncoder.encode(userInfo.getPassword()));return userDao.insertUser(userInfo);}
}

对应的xml文件的sql如下:

    <insert id="insertUser">insert into user(username,password) values (#{userInfo.username},#{userInfo.password})</insert>

配置类要改的内容如下

在这里插入图片描述

package com.masiyi.springsecuritydemo.config;import com.masiyi.springsecuritydemo.handler.MyAuthenticationFailureHandler;
import com.masiyi.springsecuritydemo.handler.MyAuthenticationSuccessHandler;
import com.masiyi.springsecuritydemo.handler.MyLogoutSuccessHandler;
import com.masiyi.springsecuritydemo.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {/*** 这里有两种方式 authorizeHttpRequests 和 authorizeRequests* @param http the {@link HttpSecurity} to modify* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeHttpRequests().mvcMatchers("/user/register").permitAll().anyRequest().authenticated().and().formLogin().successHandler(new MyAuthenticationSuccessHandler()).failureHandler(new MyAuthenticationFailureHandler()).and().logout().logoutSuccessHandler(new MyLogoutSuccessHandler()).and().csrf().disable();}
//
//    @Bean
//    public UserDetailsService userDetailsService() {
//        InMemoryUserDetailsManager inMemoryUserDetailsManager
//                = new InMemoryUserDetailsManager();
//        UserDetails u1 = User.withUsername("masiyi")
//                .password("{noop}111").roles("USER").build();
//        inMemoryUserDetailsManager.createUser(u1);
//        return inMemoryUserDetailsManager;
//    }@Beanpublic UserDetailsService userDetailsService() {return new MyUserDetailService();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());}/*** 指定加密方式*/@Beanpublic PasswordEncoder passwordEncoder() {// 使用BCrypt加密密码return new BCryptPasswordEncoder();}
}

至此spring security实现自定义用户配置,我们就讲到这里。下面我会给大家讲一下spring security的授权的功能。

项目的地址就在
https://gitee.com/WangFuGui-Ma/spring-security-admin
如果大家对这篇文章或者专栏有兴趣或者对大家有所帮助的话,欢迎关注点赞。加评论。
我们spring security的进阶专栏见。

在这里插入图片描述

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

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

相关文章

OpenHarmony 实战开发——ArkUI canvas组件

canvas 是 ArkUI 开发框架里的画布组件&#xff0c;常用于自定义绘制图形。因为其轻量、灵活、高效等优点&#xff0c;被广泛应用于 UI 界面开发中。本期&#xff0c;我们将为大家介绍 ArkUI 开发框架中 canvas 组件的使用。 一、canvas 介绍 1.1 什么是 canvas&#xff1f; …

rocketmq的存储和检索

messageId是rocketmq自动生成的。

Java的response返回Json格式

问题 今天开发过程中&#xff0c;写了个拦截器&#xff0c;对于所以请求进行一个token的工作&#xff0c;对于不合标准的token返回错误&#xff0c;在网上找了个拦截器进行二次开发。 package com.maizhiyu.yzt.handle;import org.springframework.beans.factory.annotation.…

AWS Lambda配置CloudWatch日志

Hello example&#xff1a;AWS Lambda 第一个例子Hello (JAVA)-CSDN博客 创建lambda函数&#xff0c;测试&#xff0c;然后点击CloudWatch日志 CloudWatch日志组不存在 创建CloudWatch日志组 1) CloudWatch -> 日志组 -> 创建日志组 2) 填写名称&#xff0c;创建 添加权…

掌握这些神器,让你的编程之路更加“丝滑”

前言&#xff1a; 在软件开发的旅程中&#xff0c;程序员的实用神器确实如同指南针&#xff0c;帮助他们在复杂的代码海洋中导航。以下是从三个方向——自动化测试工具、持续集成/持续部署&#xff08;CI/CD&#xff09;以及代码审查与质量分析——来探讨这些实用神器的应用和影…

SC8908电机驱动芯片替代AN41908

SC8908 描述 五路H桥静音驱动电机驱动芯片&#xff0c;闭环直流电机光圈调节&#xff0c;支持霍尔位置检测&#xff0c; 2个步进电机。步进电机驱动带256微步细分。 主要特性 • 步进驱动H桥每路250mA最大驱动电流 • 光圈直流驱动H桥每路150mA最大驱动电流 • 单独…

1725 ssm资产管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java ssm资产管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/…

libssh C++封装之六(Dir)

1 概述 libssh是一个在客户端和服务器端实现SSHv2协议的多平台C库。使用libssh,您可以远程执行程序、传输文件、使用安全透明的隧道、管理公钥等等。本文描述的对libssh客户端功能的C++封装。 libssh下载地址 3 实现 3.5 Dir Dir类型管理远程路径,通过SFTP和Channel实现(有…

uni u-form-item 只有图标点击有效

如下,输入的地方是个选择项,代码如下: <u-form-item class=u-form-item label="监督主题" prop="themeName" borderBottom ref="item1" @click="openPopup(0)" > <u--input v-model="form.themeNam…

定时发圈操作介绍

1、登陆已有的账号&#xff0c;点击到"朋友圈"功能 2、选择要发圈的微信号&#xff0c;编辑发圈的文案内容 3、自定义想要的时间点 4、点击"立即发送" 5、可进行跟圈

深度解析 Spring 源码:解密AOP切点和通知的实现机制

文章目录 深度解析 Spring 源码&#xff1a;解密AOP切点和通知的实现机制一、Spring AOP的基础知识1.1 AOP的核心概念&#xff1a;切点、通知、切面等1.2 Spring AOP与传统AOP的区别和优势 二、深入分析切点和通知的实现2.1 研究 Pointcut 接口及其实现类2.1.1 Pointcut 接口2.…

数据库审计系统Yearning使用笔记

一、启动 1、初始化MySQL 启动mysql docker run -d --namemysql -p 3306:3306 -e MYSQL_ROOT_PASSWORDroot mysql:5.7创建数据库&#xff0c;链接数据库并执行以下创建库的脚步&#xff0c;注意字符集 create database yearning char set utf8mb42、启动Yeelabs 需要执行…

CDGA|揭秘移动物联网数据治理秘诀,轻松提升数据质量,赋能智慧未来

在数字化浪潮汹涌的今天&#xff0c;移动物联网作为连接物理世界与数字世界的桥梁&#xff0c;其数据治理的重要性日益凸显。高质量的数据不仅是企业决策的基石&#xff0c;更是推动行业智能化、精细化发展的关键。本文将为您揭秘移动物联网数据治理的技巧&#xff0c;助您轻松…

如何设计实用的ITSM自助服务台

在现代IT服务管理&#xff08;ITSM&#xff09;领域中&#xff0c;自助服务台已成为IT运维环境的核心组件。它作为企业内部信息中心与其他部门用户之间的桥梁&#xff0c;一个以用户为中心的平台&#xff0c;更注重用户的自主性和自助能力&#xff0c;使用户能够直接访问所需的…

微软宣布GPT-4o模型,可在 Azure OpenAI上使用

5月14日&#xff0c;微软在官网宣布&#xff0c;OpenAI最新发布的多模态模型GPT-4o&#xff0c;可以在 Azure OpenAI 云服务中使用。 据悉&#xff0c;GPT-4o支持跨文本、视频、音频多模态推理&#xff0c;例如&#xff0c;通过GPT-4o打造一个AI助手&#xff0c;用于辅导孩子解…

基于NIOS-II软核流水灯和串口通信实现

文章目录 一、创建工程二、系统设计1. 在 “component library” 标签栏中找到 “Nios II Processor” 后点击 Add2. 在 ”Component Library” 标签栏中的查找窗口输入 jtag 找到 ”JTAG UART ”&#xff0c;然后点击 Add3. 添加片上存储器 On-Chip Memory(RAM)核4. 查找窗口输…

做简单易用的GIS资源管理软件

在室外资源管理领域&#xff0c;采用基于GIS的解决方案已成为主流趋势&#xff0c;旨在实现资源的高效利用和管理。GIS技术结合资源对象的规划、定位和监控&#xff0c;为企业提供全面的管理方案&#xff0c;从而优化资源使用、提高运营效率和降低成本。 然而&#xff0c;许多资…

龙迅LT8911EX LVDS桥接到EDP,支持4K30HZ分辨率

龙迅LT8911EX描述&#xff1a; Lontium LT8911EX是LVDS到eDP转换器&#xff0c;具有单端口或双端口可配置的LVDS接收器&#xff0c;有1个时钟通道和最多8个数据通道&#xff0c;每个数据通道最大运行1.2Gbps&#xff0c;最大输入带宽为9.6Gbps。转换器将输入LVDS数据去序列化&…

OpenNJet产品体验:探索无限可能

文章目录 前言一、OpenNJet是什么&#xff1f;二、OpenNJet特性和优点三、OpenNJet功能规划四、OpenNJet快速上手五、OpenNJet的使用总结 前言 现代社会网络高速发展&#xff0c;同时也迎来了互联网发展的高峰&#xff0c;OpenNJet作为一个基于NGINX的面向互联网和云原生应用提…

掏心经验分享,软考中项0基础入门篇!

想备考下半年中项&#xff08;系统集成项目管理工程师&#xff09;的朋友&#xff0c;不知道如何了解软考中项&#xff0c;今天给大家整理一篇关于我自己在备考软考时的一些考量和踩过的一些坑。&#xff08;无广&#xff0c;放心看&#xff09; 很多小伙伴总是听大家说软考中…