SpringSecurity学习(二)自定义资源认证规则、自定义登录页面、自定义登录(成功/失败)处理、用户信息获取

news2024/11/16 1:26:28

文章目录

  • 一、自定义认证
    • 1. 自定义资源权限规则
  • 二、自定义登录页面
    • 1. 引入thymeleaf依赖,并配置
    • 2. 配置SecurityCfg的securityFilterChain实例
    • 3. 编写login.html
    • 注意:
  • 三、自定义登录成功处理
    • 1. 编写JsonAuthenticationSuccessHandler处理器,返回JSON数据
    • 2. 修改SecurityFilterChain 配置
  • 四、自定义登录失败页面跳转,信息显示
    • 1. 修改SecurityFilterChain 配置
    • 2. 修改login.html
  • 五、自定义登录失败处理器
    • 1. 修改SecurityFilterChain配置
    • 2. 编写JsonAuthenticationFailHandler
  • 六、注销登录
    • 1. 单个注销登录请求配置
    • 2. 多个注销登录请求接口配置
  • 七、自定义注销登录处理器
    • 1. 修改SecurityFilterChain配置
  • 八、获取用户认证信息
    • 1. SecurityContextHolder
      • MODE_THREADLOCAL(默认存储策略)
      • MODE_INHERITABLETHREADLOCAL
      • MODE_GLOBAL
    • 2. SecurityContextHolderStrategy
    • 3. 测试
      • MODE_THREADLOCAL
      • MODE_INHERITABLETHREADLOCAL
  • 九、页面中获取用户认证信息

一、自定义认证

1. 自定义资源权限规则

  • /index 公共资源
  • /hello 受保护资源
    在这里插入图片描述在项目中添加如下配置就可以实现对资源权限规则的设定:
@Configuration
public class WebSecurityCfg extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(req -> {
            // 注意:这里放行的内容必须在验证之前
            // mvcMatchers匹配资源,permitAll放行该资源,无需认证授权,直接访问
            req.mvcMatchers("/index").permitAll();
            // anyRequest所有请求,都需要认证才可访问
            req.anyRequest().authenticated();
            // formLogin()  开启表单认证
        }).formLogin();
    }
}

在这里插入图片描述
由于官方提示WebSecurityConfigurerAdapter 已过时,我们按照官方提示来使用以下新的配置:

// 注意这里必须加上注解@EnableWebSecurity,否则配置不能生效
@EnableWebSecurity
public class SecurityCfg {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index").permitAll();
            req.anyRequest().authenticated();
        }).formLogin();
        return http.build();
    }
}

二、自定义登录页面

1. 引入thymeleaf依赖,并配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spring:
  thymeleaf:
    cache: false
    prefix: classpath:/templates/
    suffix: .html
    check-template-location: true
    encoding: UTF-8
    mode: HTML
    servlet:
      content-type: text/html

2. 配置SecurityCfg的securityFilterChain实例

@EnableWebSecurity
public class SecurityCfg {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 设置默认成功页面 成功重定向。 注意:与successForwardUrl只能设置一个
                .defaultSuccessUrl("/hi");
                // 成功 转发
//                .successForwardUrl("/hi");
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

3. 编写login.html

<!-- @author:Huathy
     @CSDN: https://blog.csdn.net/qq_40366738 -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h1>用 户 登 录</h1>
<!-- th:action="@{/doLogin}这里必须这样写,请求地址localhost:port/doLogin  否则请求地址为page/下面 -->
<form method="post" th:action="@{/doLogin}">
<!--  这里需要注意:如果要使用自定义的参数名称必须在SecurityFilterChain中进行配置  -->
    UserName: <input name="uname" type="text" value="admin"/><br/>
    Password: <input name="pwd" type="text" value="admin"/><br/>
    <!--    这里在security自带的还有一个隐藏的csrf的属性。csrf:跨站请求伪造攻击-->
    <!--    <input name="_csrf" type="hidden" value="xxx">-->
    <input type="submit" value="登录">
</form>
</body>
</html>

注意:

  1. SecurityFilterChain中需要先暂时关闭CSRF跨站请求伪造攻击防御。 http.csrf().disable();
  2. 指定登陆页面,必须同时指定登录地址。http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
  3. 成功返回页defaultSuccessUrl("/hi")successForwardUrl("/hi")只能配置一个。前者默认重定向redirect到refer地址,如果没有refer就跳转defaultURL,可以通过alwaysUse参数配置是否要回跳之前访问的URL。后者默认使用forward转发到设定的URL地址。

三、自定义登录成功处理

在前后端分离的情况下,登录成功之后不需要跳转页面,而是需要返回一个JSON通知前端是否登录成功。这时,可以通过自定义AuthenticationSuccessHandler来实现。

package org.springframework.security.web.authentication;

public interface AuthenticationSuccessHandler {
    default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
        this.onAuthenticationSuccess(request, response, authentication);
        chain.doFilter(request, response);
    }
// 覆盖该方法即可
    void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}

在这里插入图片描述

1. 编写JsonAuthenticationSuccessHandler处理器,返回JSON数据

package com.hx.demo.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

/**
 * @author Huathy
 * @date 2023-02-28 22:56
 * @description 自定义的成功处理器,返回JSON数据
 */
public class JsonAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Map<String, Object> result = new HashMap<>();
        result.put("msg", "登录成功");
        result.put("code", 200);
        result.put("authentication", authentication);
        response.setContentType("application/json;charset=UTF-8");
        String jsonData = new ObjectMapper().writeValueAsString(result);
        response.getWriter().write(jsonData);
    }
}

2. 修改SecurityFilterChain 配置

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler());
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

四、自定义登录失败页面跳转,信息显示

通过debug类org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler#saveException,可以知道以下内容:
如果是forward,异常信息存入request
如果是redirect默认,异常信息存入session
key:SPRING_SECURITY_LAST_EXCEPTION
在这里插入图片描述

1. 修改SecurityFilterChain 配置

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler())
                .failureForwardUrl("/page/login.html");
//                .failureUrl("/page/login.html");
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

2. 修改login.html

<!-- @author:Huathy
     @CSDN: https://blog.csdn.net/qq_40366738 -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<!-- 增加错误信息配置,这里从SESSION中获取或者从Request中获取 -->
<h5>错误信息:</h5>
<div>req:<span th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></span></div>
<div>session:<span th:text="${session.SPRING_SECURITY_LAST_EXCEPTION}"></span></div>

<h1>用 户 登 录</h1>
<form method="post" th:action="@{/doLogin}">
    <!--  这里需要注意:如果要使用自定义的参数名称必须在SecurityFilterChain中进行配置  -->
    UserName: <input name="uname" type="text" value="admin"/><br/>
    Password: <input name="pwd" type="text" value="123"/><br/>
    <!--    这里在security自带的还有一个隐藏的csrf的属性。csrf:跨站请求伪造攻击-->
    <!--    <input name="_csrf" type="hidden" value="xxx">-->
    <input type="submit" value="登录">
</form>

</body>
</html>

五、自定义登录失败处理器

这里与自定义登录成功处理器类似
在这里插入图片描述

1. 修改SecurityFilterChain配置

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler())
                .failureHandler(new JsonAuthenticationFailHandler());
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

2. 编写JsonAuthenticationFailHandler

package com.hx.demo.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

/**
 * @author Huathy
 * @date 2023-03-01 19:37
 * @description
 */
public class JsonAuthenticationFailHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        Map<String, Object> result = new HashMap<>();
        result.put("msg", "登录失败");
        result.put("code", 500);
        result.put("exception", exception.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        String jsonData = new ObjectMapper().writeValueAsString(result);
        response.getWriter().write(jsonData);
    }
}

六、注销登录

SpringSecurity中也提供了注销登录配置,在开发时也可以按照自己需求对注销进行个性化定制。默认是开启注销登录的。默认地址为:http://ip:prot/path/logout。

1. 单个注销登录请求配置

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler())
                .failureHandler(new JsonAuthenticationFailHandler());
        http.logout().logoutUrl("logout")   //注销登录URL,默认请求方式为GET请求
                .invalidateHttpSession(true)    // 会话失效httpSession,默认true
                .clearAuthentication(true)     // 清除认证信息,默认true
                .logoutSuccessUrl("/index.html");   // 注销登录,成功跳回首页
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}
  • 通过logout()方法开启注销配置
  • logoutUrl()指定退出登录请求地址,默认GET请求,路径 /logout
  • invalidateHttpSession 退出时是否是session失败,默认true
  • clearAuthentication退出时是否清除认证信息,默认true
  • logoutSuccessUrl 退出登录时跳转地址

2. 多个注销登录请求接口配置

如果项目中需要多个注销接口,可以通过配置,还可以指定请求方法。

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler())
//                .failureForwardUrl("/page/login.html");
//                .failureUrl("/page/login.html");
                .failureHandler(new JsonAuthenticationFailHandler());
        // 这里只配置一个也可以,修改默认请求方式。
        http.logout().logoutRequestMatcher(new OrRequestMatcher(
                new AntPathRequestMatcher("/logout", RequestMethod.GET.name()),
                new AntPathRequestMatcher("/unLogin", RequestMethod.GET.name())
        ));
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

七、自定义注销登录处理器

在这里插入图片描述

1. 修改SecurityFilterChain配置

http.logout().logoutSuccessHandler(new JsonLogoutSucceessHandler());

@EnableWebSecurity
public class SecurityCfg2 {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(req -> {
            req.mvcMatchers("/index", "/page/login.html").permitAll();
            req.anyRequest().authenticated();
        });
        //loginPage 指定默认登陆页面。这里需要注意:在自定义登陆页面后,必须指定登录地址
        http.formLogin().loginPage("/page/login.html").loginProcessingUrl("/doLogin")
                // 对参数用户名、密码的参数名进行设置
                .usernameParameter("uname").passwordParameter("pwd")
                // 认证成功处理器
                .successHandler(new JsonAuthenticationSuccessHandler())
                .failureHandler(new JsonAuthenticationFailHandler());
        http.logout().logoutSuccessHandler(new JsonLogoutSucceessHandler());
        // 禁用csrf跨站请求伪造攻击防护
        http.csrf().disable();
        return http.build();
    }
}

八、获取用户认证信息

1. SecurityContextHolder

SpringSecurity学习(一)整体架构——1.3 SecurityContextHolder
在这里插入图片描述服务器端session默认为无操作后30分钟过期。
实际上SecurityContextHolder中存储的是SecurityContext,在SecurityContext中存储的是Authentication。
在这里插入图片描述 这种设计模式,是典型的策略模式(适配器模式)。

// 这里只对关键部分代码做截取
package org.springframework.security.core.context;
public class SecurityContextHolder {
	public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
	public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
	public static final String MODE_GLOBAL = "MODE_GLOBAL";
	private static final String MODE_PRE_INITIALIZED = "MODE_PRE_INITIALIZED";
	private static void initialize() {
		initializeStrategy();
		initializeCount++;
	}
	private static void initializeStrategy() {
		if (MODE_PRE_INITIALIZED.equals(strategyName)) {
			Assert.state(strategy != null, "When using " + MODE_PRE_INITIALIZED
					+ ", setContextHolderStrategy must be called with the fully constructed strategy");
			return;
		}
		if (!StringUtils.hasText(strategyName)) {
			// Set default
			strategyName = MODE_THREADLOCAL;
		}
		if (strategyName.equals(MODE_THREADLOCAL)) {
			strategy = new ThreadLocalSecurityContextHolderStrategy(); return;
		}
		if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
			strategy = new InheritableThreadLocalSecurityContextHolderStrategy(); return;
		}
		if (strategyName.equals(MODE_GLOBAL)) {
			strategy = new GlobalSecurityContextHolderStrategy(); return;
		}
		// Try to load a custom strategy
	}
	public static void clearContext() {
		strategy.clearContext();
	}
	public static SecurityContext getContext() {
		return strategy.getContext();
	}
}

MODE_THREADLOCAL(默认存储策略)

本地线程策略,是将SecurityContext存放在ThreadLocal中。而ThreadLocal的特点是在哪个线程中存储,就在哪个线程中读取。由于默认情况下,一个请求无论经过多少Filter到达Servlet,都是由一个线程处理的,所以其实非常适合web应用。但如果在业务代码中开启了子线程,那么在子线程中是无法获取用户登录数据的。

MODE_INHERITABLETHREADLOCAL

这种存储模式,适用于多线程环境,如果希望在子线程中也能获取到用户登录数据,可以采用该种模式。

MODE_GLOBAL

这种存储模式实际上是将数据保存在一个静态变量中,在JavaWeb开发中,很少使用。

2. SecurityContextHolderStrategy

通过SecurityContextHolder可以得知,SecurityContextHolderStrategy接口用来定义存储策略方法。

public interface SecurityContextHolderStrategy {
	/**
	 * 清除存储的SecurityContext对象。Clears the current context.
	 */
	void clearContext();
	/**
	 * 获取存储的SecurityContext对象。Obtains the current context.
	 */
	SecurityContext getContext();
	/**
	 * 设置存储的SecurityContext对象。Sets the current context.
	 */
	void setContext(SecurityContext context);
	/**
	 * 创建一个空的SecurityContext对象。Creates a new, empty context implementation, for use by
	 */
	SecurityContext createEmptyContext();
}

在这里插入图片描述

3. 测试

  1. 修改HiController中的hi接口方法
@RestController
public class HiController {
    @RequestMapping("/hi")
    public String hi() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("身份信息:authentication.getPrincipal() = " + authentication.getPrincipal());
        System.out.println("权限信息:authentication.getAuthorities() = " + authentication.getAuthorities());
        System.out.println("凭证信息:authentication.getCredentials() = " + authentication.getCredentials());
        new Thread(()->{
            Authentication authentication1 = SecurityContextHolder.getContext().getAuthentication();
            System.out.println("子线程 - 身份信息: = " + authentication1);
        }).start();
        return "<h1>HI Spring Security</h1>";
    }
}

MODE_THREADLOCAL

在这里插入图片描述

MODE_INHERITABLETHREADLOCAL

需要配置VM启动参数-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
这种模式下,启动多线程,会拷贝父线程的数据
在这里插入图片描述
在这里插入图片描述

九、页面中获取用户认证信息

由于这是传统的web开发获取方式,这里只做简单的使用案例:

  1. 引入依赖
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    <version>3.0.4.RELEASE</version>
</dependency>
  1. 导入命名空间,与页面编写
<!-- @author:Huathy
     @CSDN: https://blog.csdn.net/qq_40366738 -->
<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
>
<head>
    <meta charset="UTF-8">
</head>
<body>

<h5>用户信息</h5>
<ul>
    <li sec:authentication="principal.username"></li>
    <li sec:authentication="principal.authorities"></li>
    <li sec:authentication="principal.accountNonExpired"></li>
    <li sec:authentication="principal.accountNonLocked"></li>
    <li sec:authentication="principal.credentialsNonExpired"></li>
</ul>
</body>
</html>
  1. 访问:http://localhost:8888/page/logout.html
    在这里插入图片描述

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

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

相关文章

如何在excel中创建斐波那契数列

斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列&#xff0c;因数学家莱昂纳多斐波那契&#xff08;Leonardo Fibonacci&#xff09;以兔子繁殖为例子而引入&#xff0c;故又称为“兔子数列”&#xff0c;指的是这样一个数列&#xff1a;…

软件测试是个人就能做?恕我直言,你可能是个“纯粹”的测试工具人,BUG收集器

作为过来人的我和你说说软件测试的真正情况。 前言 一个软件做出来&#xff0c;最不能少的是谁&#xff1f;毫无疑问是开发&#xff0c;开发是最了解软件运作的那个人&#xff0c;早期就有不少一人撸网站或者APP的例子&#xff0c;相当于一个人同时是产品、研发、测试、运维等…

学习笔记-架构的演进之服务容错策略-服务发现-3月day01

文章目录前言服务容错容错策略附前言 “容错性设计”&#xff08;Design for Failure&#xff09;是微服务的一个核心原则。 使用微服务架构&#xff0c;拆分出的服务越来越多&#xff0c;也逐渐导致以下问题&#xff1a; 某一个服务的崩溃&#xff0c;会导致所有用到这个服务…

webrtc拥塞控制算法对比-GCC vs BBR vs PCC

1.前言现有集成在webrtc中的拥塞控制算法有三种, 分别是: 谷歌自研发的gcc, 谷歌自研发的BBR算法, 斯坦福大学提出的基于机器学习凸优化的PCC算法. 本文将探讨一下三个算法的区别和优缺点。2.背景迈聆会议从17年到现在, 一直使用的是基于谷歌的gcc算法自研的Omcc算法(optimizat…

【基于机器学习的推荐系统项目实战-1】初识推荐系统

本文目录一、为什么我们需要推荐系统&#xff1f;二、推荐系统的发展阶段三、推荐系统模型四、通用推荐系统框架4.1 数据生产4.2 数据存储4.3 算法召回4.4 结果排序4.5 结果应用4.6 新浪微博的框架开源结构图五、推荐常用特征5.1 用户特征5.2 物品特征六、推荐常用算法七、结果…

正点原子IMX6ULL开发板-liunx内核移植例程-uboot卡在Starting kernel...问题

环境 虚拟机与Linux版本&#xff1a; VMware 17.0.0 Ubuntu16 NXP提供的U-boot与Linux版本&#xff1a; u-boot:uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2 linux:linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2 开发板&#xff1a; 正点原子-IMX6ULL_EMMC版本&#xff0c;底板版…

国产光刻机再突破后,能实现7nm芯片量产?专家:别再盲目自大

众所周知&#xff0c;不能生产高端芯片&#xff0c;一直都是我国芯片产业一个无法抹去的痛。加上老美近几年的刻意打压&#xff0c;部分中芯企更是苦不堪言&#xff0c;因此大部分人心里也都憋着一口气&#xff0c;这几年也是铆足了劲&#xff0c;大力推动国产芯片技术的发展。…

小家电品牌私域增长解决方案来了

小家电品牌的私域优势 01、行业线上化发展程度高 相对于大家电动辄上千上万元的价格&#xff0c;小家电的客单价较低。而且与大家电偏刚需属性不同的是&#xff0c;小家电的消费需求侧重场景化&#xff0c;用户希望通过购买小家电来提高自身的生活品质。这就决定了用户的决策…

【数组】JavaScript 全栈体系(六)

JavaScript 基础 第十章 循环-for 一、for循环基本使用 实现循环的 3 要素 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><…

嘉宾阵容公布 | Impact Tech, She Can 2023 对话升级

2023 年&#xff0c;在三八妇女节来临之际&#xff0c;Jina AI 联合将门创投、OpenMMLab、亚马逊云科技、稀土掘金、开源中国、CSDN等 14 家科技行业伙伴&#xff0c;发起了第二届「Impact Tech, She Can」线上对话。活动信息通过 2 场圆桌对话、1 场技术分享&#xff0c;希望让…

函数栈帧详解

写在前面 这个模块临近C语言的边界&#xff0c;学起来需要一定的时间&#xff0c;不过当我们知道这些知识后&#xff0c;在C语言函数这块我们看到的不仅仅是表象了&#xff0c;可以真正了解函数是怎么调用的。不过我的能力有限&#xff0c;下面的的知识若是不当&#xff0c;还…

一些关于linux process 和python process的记录

python mulprocess 主要用来生成另一个进程并运行 def func(i):print(helloworld)from multiprocessing import Process p Process(targetfunc,args(i, )) p.start()如果想要调用shell命令&#xff0c;可以采用os.popen 或者是 subprocess.run 但是前者只能执行命令并获取输…

【链表OJ题(二)】链表的中间节点

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录链表OJ题(二)1. 链表…

每日学术速递3.1

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Directed Diffusion: Direct Control of Object Placement through Attention Guidance 标题&#xff1a;定向扩散&#xff1a;通过注意力引导直接控制物体放置 作者&#xff1a;…

Kafka入门(六)

下面聊聊Kafka中的Offset位移 1、Offset位移概述 在引入Kafka服务后&#xff0c;当consumer消费完数据后需要进行位移提交&#xff0c;那么提交的位移数据究竟存储到那里&#xff0c;有以何种方式进行存储&#xff1f; Kafka旧版本&#xff08;<0.8&#xff09;是重度依赖Z…

【python学习】批量从含有多列数据的txt文件中提取某个数据,并存入csv文件

批量从含有多列数据的txt文件中提取某个数据&#xff0c;并存入csv文件任务需求与解读代码实现导入相关库提取txt文件的三列数据存为列表按条件提取某个数据存入字典将字典写入csv文件任务需求与解读 昨天收到一个需求&#xff0c;希望能将电化学工作站的数据文件(.bin后缀)转…

欧文数据建模师 erwin Data Modeler Crack

欧文数据建模师 erwin Data Modeler 是一款屡获殊荣的数据建模工具&#xff0c; 用于查找、可视化、设计、部署和标准化高质量的企业数据资产。从任何地方发现和记录任何数据&#xff0c;以在大规模数据集成、主数据管理、元数据管理、大数据、商业智能和分析计划中实现一致性、…

kubernetes--安全沙箱运行容器gVisor

gVisor介绍 所知&#xff0c;容器的应用程序可以直接访问Linux内核的系统调用&#xff0c;容器在安全隔离上还是比较弱&#xff0c;虽然内核在不断的增强自身的安全特性&#xff0c;但由于内核自身代码极端复杂&#xff0c;CVE漏洞层出不穷。 所以要想减少这方面安全风险&#…

MATLAB | 这些花里胡哨的热图怎么画

好早之前写过一个绘制相关系数矩阵的代码&#xff0c;但是会自动求相关系数&#xff0c;而且画出来的热图只能是方形&#xff0c;这里写一款允许nan值出现&#xff0c;任意形状的热图绘制代码&#xff0c;绘制效果如下&#xff1a; 如遇到bug请后台提出&#xff0c;并去gitee下…

Spring Boot+Vue前后端分离项目练习02之网盘项目利用token进行登陆验证

1.添加依赖 首先需要添加jwt对应的依赖。 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>2.添加配置 JWT由三部分构成&#xff0c;分别是 header, pa…