SpringSecurity深度学习

 SpringSecurity简介

spring Security是什么?

Spring Security 是一个强大且高度可定制的身份验证和访问控制框架,用于保护基于Spring的应用程序。它是Spring项目的一部分,旨在为企业级系统提供全面的安全性解决方案。

一个简单的授权和校验流程

检验流程

总流程 

SpringSecurity使用

认证 

对应依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

在自定义检验的时候,主要就是实现UserDetailsService接口,重写loadUserByUserName方法,在该方法中就是去检验账号和密码的准确性。(一般都是进行数据库的查询校验,默认的密码格式就是 ·{}密码·)

前后端分离项目登录流程

1.在springSecurity中我们的需要设置密文的配置,在项目中大多都是使 BCryptPasswordEncoder类来做密码的加密。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


}

2.创建对应的login接口和service

Controller 

@RestController
@RequestMapping("/user")
public class LoginController {

    @Autowired
    LoginService loginService;

    @PostMapping("/login")
    public ResponseResult login(@RequestBody User user) {
        return loginService.login(user);
    }
}

Service

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    RedisCache redisCache;
    @Override
    public ResponseResult login(User user) {
        //authenticationManager authenticate进行用户验证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //执行我们对饮的认证方法,在该方法中会返回LoginUser类型的数据
        //如果没有通过通过直接抛异常
        if(ObjectUtil.isEmpty(authenticate)) {
            throw new RuntimeException("登录失败");
        }
        //如果成功直接生成token,将其也map返回
        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
        String jwt = JwtUtil.createJWT(loginUser.getUser().getId().toString());
        Map<String, String> data = new HashMap<>();
        data.put("token", jwt);
        redisCache.setCacheObject(loginUser.getUser().getId().toString(), user);
        //返回token
        return new ResponseResult(200, "登录成功", data);
    }
}

因为AuthenticationManager默认不在ioc中,我们需要将其配置到ioc中,并且配置对应的校验规则。在里面就包括 无效校验的接口(比如:登录接口)和其他一些前后端分离的配置。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //将AuthenticationManager配置到ioc中
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //由于是前后端分离项目,所以要关闭csrf
                .csrf().disable()
                //由于是前后端分离项目,所以session是失效的,我们就不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //指定让spring security放行登录接口的规则
                .authorizeRequests()
                // 对于登录接口 anonymous表示允许匿名访问
                .antMatchers("/user/login").anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();
    }
}

进行测试,校验成功。

前后端分离项目校验流程

1.创建一个校验过滤器

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    RedisCache redisCache;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取token,token会存在header中
        String token = request.getHeader("token");
        if(StrUtil.isEmpty(token)) {
            //由后续的拦截器进行拦截
            filterChain.doFilter(request, response);
            //后续会返回回来,需要return,不然会执行下面的语句
            return ;
        }
        //解析token
        String userId;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userId = claims.getSubject();
            if(StringUtil.isNullOrEmpty(userId)) {
                throw new RuntimeException("token解析失败");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        //从redis中获取用户的信息
        LoginUser loginUser = redisCache.getCacheObject(userId);
        if(ObjectUtil.isEmpty(loginUser)) {
            throw new RuntimeException("Redis中没有用户信息");
        }
        //将数据存储到SecurityContextHolder
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
    }
}

使用三个参数的UsernamePasswordAuthenticationToken的构造器,该构造器会设置授权成功。

2.将过滤器设置到用户验证过滤器之前

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    //设置加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //将AuthenticationManager配置到ioc中
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //由于是前后端分离项目,所以要关闭csrf
                .csrf().disable()
                //由于是前后端分离项目,所以session是失效的,我们就不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //指定让spring security放行登录接口的规则
                .authorizeRequests()
                // 对于登录接口 anonymous表示允许匿名访问
                .antMatchers("/user/login").anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();


        //将过滤器添加到用户登录处理器之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

进行测试,将成功的token放入header中,进行校验。最终校验成功。

退出登录流程

1.编写退出登录接口

@RestController
@RequestMapping("/user")
public class LoginController {

    @Autowired
    LoginService loginService;


    @RequestMapping("/logout")
    public ResponseResult logout() {
        return loginService.logout();
    }
}

2.编写service实现类,删除redis中用户信息的数据,即可完成退出登录操作。在解析的时候redis中的数据不存在就会直接被拦截。

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    RedisCache redisCache;


    @Override
    public ResponseResult logout() {
        //在进入此接口时会先进行解析,成功之后才会执行logout,此时SecurityContextHolder中是有用户信息的
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        if(ObjectUtil.isEmpty(loginUser)) {
            throw new RuntimeException("LoginUser不存在");
        }
        //把redis中的数据删除之后,下次解析的时候就会直接报错,在解析中我们对redis的数据做了判空的操作
        redisCache.deleteObject(loginUser.getUser().getId().toString());
        return new ResponseResult(200, "退出登录成功", null);
    }
}

进行测试,最终成功。

授权

1.开启授权功能,在对应的security的配置类中添加对应的注解。

@EnableGlobalMethodSecurity(prePostEnabled = true) //开启授权

2.为接口设置对应的权限需求

@RestController
public class baseController {

    @RequestMapping("/hello")
    //拥有text倾向才能访问
    @PreAuthorize("hasAuthority('text')")
    public String hello() {
        return "hello!";
    }
}

3.在用户进行认证的时候查询用户拥有的权限集合,并设置到 authenticationToken中。

  • 在返回类型中设置权限集合属性和重写获取权限集合方法。
@Data
@NoArgsConstructor
public class LoginUser implements UserDetails {

    private User user;

    private List<String> authorities2String;

    public LoginUser(User user, List<String> authorities2String) {
        this.user = user;
        this.authorities2String = authorities2String;
    }

    @JSONField(serialize = false)
    private List<GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if(CollUtil.isEmpty(authorities)) {
            return authorities2String.stream()
                    .map(item -> new SimpleGrantedAuthority(item))
                    .collect(Collectors.toList());
        }
            return authorities;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}
  • 在校验Service中查询对应的权限列表。
@Service
public class UserService implements UserDetailsService {

    @Autowired
    UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<com.huang.springsecuritydemo.entity.User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", username);
        com.huang.springsecuritydemo.entity.User user = userMapper.selectOne(userQueryWrapper);
        if(ObjectUtil.isEmpty(user)) {
            throw new RuntimeException("用户不存在");
        }
        //todo 查询并设置对应的权限信息
        //模拟查到的权限信息
        List<String> data = Arrays.asList("test", "text");

        return new LoginUser(user, data);
    }
}
  • 在JWT认证中向authenticationToken中设置权限集合,最终设置到SecurityContextHolder中。
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    RedisCache redisCache;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取token,token会存在header中
        String token = request.getHeader("token");
        if(StrUtil.isEmpty(token)) {
            //由后续的拦截器进行拦截
            filterChain.doFilter(request, response);
            //后续会返回回来,需要return,不然会执行下面的语句
            return ;
        }
        //解析token
        String userId;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userId = claims.getSubject();
            if(StringUtil.isNullOrEmpty(userId)) {
                throw new RuntimeException("token解析失败");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        //从redis中获取用户的信息
        LoginUser loginUser = redisCache.getCacheObject(userId);
        if(ObjectUtil.isEmpty(loginUser)) {
            throw new RuntimeException("Redis中没有用户信息");
        }
        //将数据存储到SecurityContextHolder
        //todo 设置对应的权限信息
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
    }
}

进行测试,授权成功。

RDAB模型例子(基本通用,看进行二次开发)

1.创建五个数据库 用户表,角色表,权限表,用户角色关联表,角色权限关联表。

2.编写SQL语句查询用户的所有权限,并使用 mybatis-plus进行封装为一个函数进行调用。

SELECT
            DISTINCT m.`perms`
        FROM
            sys_user_role ur
                LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
                LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
                LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
        WHERE
            user_id = #{id}
          AND r.`status` = 0
          AND m.`status` = 0

3.在校验是进行调用,并返回对应的权限集合。

@Service
public class UserService implements UserDetailsService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    MenuMapper menuMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<com.huang.springsecuritydemo.entity.User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", username);
        com.huang.springsecuritydemo.entity.User user = userMapper.selectOne(userQueryWrapper);
        if(ObjectUtil.isEmpty(user)) {
            throw new RuntimeException("用户不存在");
        }
        //todo 查询并设置对应的权限信息
        List<String> data = menuMapper.selectPermsByUserId(user.getId());

        return new LoginUser(user, data);
    }
}

修改接口所需要的权限。

@RestController
public class baseController {

    @RequestMapping("/hello")
    //拥有text倾向才能访问
    @PreAuthorize("hasAuthority('system:test:list')")
    public String hello() {
        return "hello!";
    }
}

进行测试,最终成功。

自定义失败处理

1.自定义授权异常处理器和校验异常处理器。

  • 校验异常处理器
//校验失败异常处理器
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        //创建统一的返回对象,设置到response中
        ResponseResult responseResult = new ResponseResult(HttpStatus.HTTP_UNAUTHORIZED, "校验失败!");
        String json = JSON.toJSONString(responseResult);
        //将统一的结果设置到Response中,本质就是将对应的数据设置到response中
        WebUtil.renderString(response, json);
    }
}
  • 授权异常处理器

//授权失败异常处理器
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        ResponseResult responseResult = new ResponseResult(HttpStatus.HTTP_UNAUTHORIZED, "授权失败!");
        String json = JSON.toJSONString(responseResult);
        WebUtil.renderString(response, json);
    }
}

对应的webUtil工具类

public class WebUtil {
    /**
     * 将字符串渲染到客户端
     *
     * @param response 渲染对象
     * @param string 待渲染的字符串
     * @return null
     */
    public static String renderString(HttpServletResponse response, String string) {
        try
        {
            response.setStatus(200);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            //将结果json以流的形式写入response中
            response.getWriter().print(string);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return null;
    }
}

2.将自定义的异常处理器进行配置

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    AccessDeniedHandler accessDeniedHandler;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //将AuthenticationManager配置到ioc中
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //由于是前后端分离项目,所以要关闭csrf
                .csrf().disable()
                //由于是前后端分离项目,没有session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //指定让spring security放行登录接口的规则
                .authorizeRequests()
                // 对于登录接口 anonymous表示允许匿名访问, permitAll就是 登录和没登录都可以访问
                .antMatchers("/user/login").anonymous() //匿名访问,未登录就可以访问
                // 除上面外的所有请求全部需要鉴权认证后访问
                .anyRequest().authenticated();
        //将过滤器添加到用户登录处理器之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        //设置自定义的异常处理器
        http.exceptionHandling()
                //校验异常处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                //授权异常处理器
                .accessDeniedHandler(accessDeniedHandler);
    }
}

进行测试,异常显示成功。

允许跨域

1.开启springboot的允许跨域。

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    //重写spring提供的WebMvcConfigurer接口的addCorsMappings方法
    public void addCorsMappings(CorsRegistry registry) {
        //设置可以跨域的映射地址
        registry.addMapping("/**")
                // 设置可以跨域的源
                .allowedOriginPatterns("*")
                // 是否允许使用cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
    }
}

2.开启springsecurity的允许跨域。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    AccessDeniedHandler accessDeniedHandler;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //将AuthenticationManager配置到ioc中
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //由于是前后端分离项目,所以要关闭csrf
                .csrf().disable()
                //由于是前后端分离项目,没有session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //指定让spring security放行登录接口的规则
                .authorizeRequests()
                // 对于登录接口 anonymous表示允许匿名访问, permitAll就是 登录和没登录都可以访问
                .antMatchers("/user/login").anonymous() //匿名访问,未登录就可以访问
                // 除上面外的所有请求全部需要鉴权认证后访问
                .anyRequest().authenticated();
        //将过滤器添加到用户登录处理器之前
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        //设置自定义的异常处理器
        http.exceptionHandling()
                //校验异常处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                //授权异常处理器
                .accessDeniedHandler(accessDeniedHandler);
        //允许跨域
        http.cors();
    }
}

最终设置完成。

自定义权限校验方法(比较灵活,可以自定义策略)

1.自定义校验类

@Component("itolen") //设置该类在ioc中的名称
public class ExpressionRoot {

    //判断权限是否存在
    public boolean hasAuthority(String authority) {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> authorities2String = loginUser.getAuthorities2String();
        return authorities2String.contains(authority);
    }
}

2.在对应的接口上调用自定义方法。

@RestController
public class baseController {

    @RequestMapping("/hello")
    //拥有text倾向才能访问
    @PreAuthorize("@itolen.hasAuthority('system:test:list')")
    public String hello() {
        return "hello!";
    }
}

进行测试。

 其他处理器 

  • 认证成功处理器和认证失败处理器
//认证成功处理器实现类
@Component
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //认证成功后就会进行该方法
        System.out.println("认证成功!");
    }
}
//认证失败处理器实现类
@Component
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        //认证失败后执行该方法
        System.out.println("认证失败!");
    }
}

 将两个类进行配置。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置校验成功处理器和校验失败处理器
        http.formLogin().successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler);
    }
}
  • 注销成功处理器
@Component
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //注销成功后执行的方法
        System.out.println("注销成功!");
    }
}

将该类进行配置。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

 
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;

  
    //配置权限规则,主要就睡要放行登录接口,不然登录接口都会被了解,以及其他不要的前后端分离的配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        //设置注销成功处理器
        http.logout().logoutSuccessHandler(logoutSuccessHandler);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

I/O流基础

1.输入/输出流 流是一组有序的数据序列&#xff0c;根据操作的类型&#xff0c;可以分为输入流和输出流两种。 Java定义的输入输出类被放在java.io包中 所有的输入流类都是抽象类InputStream&#xff08;字节输入流&#xff09;或抽象类Reader&#xff08;字符输入流&#xff…

Linux系统性能优化:七个实战经验

Linux系统的性能是指操作系统完成任务的有效性、稳定性和响应速度。Linux系统管理员可能经常会遇到系统不稳定、响应速度慢等问题&#xff0c;例如在Linux上搭建了一个web服务&#xff0c;经常出现网页无法打开、打开速度慢等现象&#xff0c;而遇到这些问题&#xff0c;就有人…

Unity中Shader的_Time精度问题

文章目录 前言一、U方向上优化二、V方向上优化在这里插入图片描述 三、最终代码1、效果2、Shader 前言 在Unity的Shader中&#xff0c;使用了_Time来达到UV的流动效果&#xff0c;普遍会出现一个问题。我们的UV值会随着时间一直增加&#xff08;uv值增加了&#xff0c;但是因为…

web学习笔记(十一)

目录 1.数据类型 1.1数据类型分类 &#xff08;1&#xff09;简单&#xff08;基本&#xff09;数据类型 &#xff08;2&#xff09;复杂&#xff08;特殊&#xff09;数据类型 1.2判断数据类型的方法 &#xff08;1&#xff09;常规判断方法&#xff1a; &#xff08;2…

用判断对齐大语言模型

1、写作动机&#xff1a; 目前的从反馈中学习方法仅仅使用判断来促使LLMs产生更好的响应&#xff0c;然后将其作为新的示范用于监督训练。这种对判断的间接利用受到无法从错误中学习的限制&#xff0c;这是从反馈中学习的核心精神&#xff0c;并受到LLMs的改进能力的制约。 2…

html5实现好看的个人博客模板源码

文章目录 1.设计来源1.1 主界面1.2 认识我界面1.3 我的文章界面1.4 我的模板界面1.5 文章内容界面 2.结构和源码2.1 目录结构2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/135368653 html5实现好看…

rust sqlx包(数据库相关)使用方法+问题解决

可以操作pgsql、mysql、mssql、sqlite 异步的&#xff0c;性能应该不错&#xff0c;具体使用有几个坑 除了sqlx库&#xff0c;还有对于具体数据库的库&#xff0c;比如postgres库 演示以pgsql为例&#xff0c;更新时间2024.1.6 官方github: sqlx github rust官方文档&#xff1…

c语言结构体学习

文章目录 前言一、结构体的声明1&#xff0c;什么叫结构体?2&#xff0c;结构体的类型3,结构体变量的创建和初始化4&#xff0c;结构体的类型5&#xff0c;结构体的初始化 二、结构体的访问1&#xff0c;结构体成员的点操作符访问2&#xff0c;结构体体成员的指针访问 三、结构…

网络连接 UDP2,UDP Connect, bind, send, recieve认知, -入门8

LWIP编程接口有RAW, NETCONN, SOCKET 2.UDP函数的理解 #define UDP_SERVER_PORT 8000 //PC side #define UDP_CLIENT_PORT 1234 // ctrl board side //PC IP address #define DEST_IP_ADDR0 192 #define DEST_IP_ADDR1 168 #define DEST_IP_ADDR2 3 #define DEST_IP_ADDR3 11…

如何安装和使用夜神模拟器连接Android Studio

目录 简介 一、安装 二、使用 三、更多资源 简介 夜神模拟器是一款在Windows平台上运行的Android模拟器软件。它能够模拟Android操作系统环境&#xff0c;让用户在电脑上轻松体验Android应用程序。夜神模拟器的功能强大&#xff0c;可以满足各种需求&#xff0c;无论是娱乐…

实现pytorch版的mobileNetV1

mobileNet具体细节&#xff0c;在前面已做了分析记录&#xff1a;轻量化网络-MobileNet系列-CSDN博客 这里是根据网络结构&#xff0c;搭建模型&#xff0c;用于图像分类任务。 1. 网络结构和基本组件 2. 搭建组件 &#xff08;1&#xff09;普通的卷积组件&#xff1a;CBL …

大模型学习第一课

学习目标&#xff1a; 大模型开源体系 学习内容&#xff1a; 大模型简述大模型性能开源体系 学习时间&#xff1a; 周四上午 10点 学习记录&#xff1a; 大模型简述 大模型是发展通用人工智能的重要途经专用模型到通用大模型实验室开源历程&#xff0c;大模型系列7B-20B-12…

k8s实践(14)--scheduler调度器和pod调度策略

一、scheduler调度器 1、kube-scheduler简介 k8s实践(10) -- Kubernetes集群运行原理详解 介绍过kube-scheduler。 kube-scheduler是运行在master节点上&#xff0c;其主要作用是负责资源的调度&#xff08;Pod调度&#xff09;&#xff0c;通过API Server的Watch接口监听新建…

C++中的new和delete

相关文章 C智能指针 文章目录 相关文章前言一、new 运算符1. operator new 函数的范围2. 在类中重载new运算符3. 分配失败 二、delete 运算符1. 内存泄露统计示例2. 在类中重载delete运算符 总结 前言 在C中&#xff0c;new和delete是用于动态内存管理的运算符&#xff0c;它们…

Halcon计算一个区域的最大内接圆 inner_circle

Halcon计算一个区域的最大内接圆 该算子用于计算一个区域的最大内接圆&#xff0c;其原型如下&#xff1a; inner_circle(Regions : :: Row, Column, Radius)参数1&#xff1a;Regions 表示输入的区域。 参数2和3&#xff1a;Row、Column为输出参数&#xff0c;表示最大内接圆…

面试经典题---6.Z字形变换

6.Z字形变换 我的解法&#xff1a; 首先定义了3个变量&#xff1a;index、add和step。 index&#xff1a;当前处理字符在原字符串中的下标&#xff1b;add&#xff1a;Z字形中相邻两个字符在原字符串中的下标之差&#xff08;非固定值&#xff0c;值随着行的改变会发生变化&am…

Linux 上 Nginx 配置访问 web 服务器及配置 https 访问配置过程记录

目录 一、前言说明二、配置思路三、开始修改配置四、结尾 一、前言说明 最近自己搭建了个 Blog 网站&#xff0c;想把网站部署到服务器上面&#xff0c;本文记录一下搭建过程中 Nginx 配置请求转发的过程。 二、配置思路 web项目已经在服务器上面运行起来了&#xff0c;运行的端…

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出 一 mainwindow.c 文件函数:1.1 自定义PDO配置2.2 主站初始化2.3 去motrorcontrol界面二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: mainwindow主界…

性能分析与调优: Linux 性能分析60秒

目录 一、实验 1.环境 2.Linux性能分析60秒 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系统 prometheus、node_exporter 192.168.204.18grafana监测GUIgrafana192.168.204.19agent 监测 主机 node_exporter192.168…

数据分析基础之《numpy(6)—IO操作与数据处理》

了解即可&#xff0c;用panads 一、numpy读取 1、问题 大多数数据并不是我们自己构造的&#xff0c;而是存在文件当中&#xff0c;需要我们用工具获取 但是numpy其实并不适合用来读取和处理数据&#xff0c;因此我们这里了解相关API&#xff0c;以及numpy不方便的地方即可 2…