cas客户端流程详解(源码解析)--单点登录

博主之前一直使用了cas客户端进行用户的单点登录操作,决定进行源码分析来看cas的整个流程,以便以后出现了问题还不知道是什么原因导致的

cas主要的形式就是通过过滤器的形式来实现的,来,贴上示例配置:

 1     <listener>2         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>3     </listener>4 5     <filter>6         <filter-name>SSO Logout Filter</filter-name>7         <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>8     </filter>9 
10     <filter-mapping>
11         <filter-name>SSO Logout Filter</filter-name>
12         <url-pattern>/*</url-pattern>
13     </filter-mapping>
14 
15     <!-- SSO单点登录认证filter -->
16     <filter>
17         <filter-name>SSO Authentication Filter</filter-name>
18         <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
19         <init-param>
20             <!-- SSO服务器地址 -->
21             <param-name>SSOServerUrl</param-name>
22             <param-value>http://sso.jxeduyun.com/sso</param-value>
23         </init-param>
24         <init-param>
25             <!-- 统一登录地址 -->
26             <param-name>SSOLoginUrl</param-name>
27             <param-value>http://www.jxeduyun.com/App.ResourceCloud/Src/index.php</param-value>
28         </init-param>
29         <init-param>
30             <!-- 应用服务器地址, 域名或者[http://|https://]{ip}:{port} -->
31             <param-name>serverName</param-name>
32             <param-value>http://127.0.0.1:9000</param-value>
33         </init-param>
34         <init-param>
35             <!-- 除了openId,是否需要返回loginName以及userId等更多信息 -->
36             <param-name>needAttribute</param-name>
37             <param-value>true</param-value>
38         </init-param>
39         <init-param>
40             <!-- 可选,不需要单点登录的页面,多个页面以英文逗号分隔,支持正则表达式形式 -->
41             <!-- 例如:/abc/.*\.jsp,/.*/index\.jsp -->
42             <param-name>excludedURLs</param-name>
43             <param-value>/site2\.jsp</param-value>
44         </init-param>
45     </filter>
46 
47     <filter-mapping>
48         <filter-name>SSO Authentication Filter</filter-name>
49         <url-pattern>/TyrzLogin/*</url-pattern>
50     </filter-mapping>
51 
52     <!-- SSO ticket验证filter -->
53     <filter>
54         <filter-name>SSO Ticket Validation Filter</filter-name>
55         <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
56         <init-param>
57             <!-- 应用服务器地址, 域名或者[http://|https://]{ip}:{port} -->
58             <param-name>serverName</param-name>
59             <param-value>http://127.0.0.1:9000</param-value>
60         </init-param>
61         <init-param>
62             <!-- 除了openId,是否需要返回loginName以及userId等更多信息 -->
63             <param-name>needAttribute</param-name>
64             <param-value>true</param-value>
65         </init-param>
66         <init-param>
67             <!-- SSO服务器地址前缀,用于生成验证地址,和SSOServerUrl保持一致 -->
68             <param-name>SSOServerUrlPrefix</param-name>
69             <param-value>http://sso.jxeduyun.com/sso</param-value>
70         </init-param>
71     </filter>
72 
73     <filter-mapping>
74         <filter-name>SSO Ticket Validation Filter</filter-name>
75         <url-pattern>/*</url-pattern>
76     </filter-mapping>

 博主用的不是官方的cas的jar包,是第三方要求的又再次封装的jar包,不过就是属性,获取用户信息的逻辑多了点,其他的还是官方的源码,博主懒 的下载官方的jar在进行一步一步的debug看源码了。

基本配置是添加4个过滤器,请求的时候可以进行拦截进行查看,最后一个是jfinal的开发框架,类似spring,不用管,

 以上是jetty抓到请求时,进行获取过滤的流程,只关注cas的这四个,里面涉及到了缓存过滤器(节点类型存储)

全部进行路径URL匹配完之后,会获取到需要进行执行的过滤器,SSO Logout Filter->SSO Authentication Filter->SSO Ticket Validation Filter->CAS Assertion Thread Local Filter->jfinal->default

那我们就来一个一个看看,每个过滤器都做了哪些事。

SSO Logout Filter,从名字上看,应该是个退出的流程操作。来源吗附上:

 1 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {2         HttpServletRequest request = (HttpServletRequest)servletRequest;3         HttpServletResponse response = (HttpServletResponse)servletResponse;4         //查看请求中是否带有ticket参数5         if (!handler.isTokenRequest(request) && !CommonUtils.isNotBlank(request.getParameter("ticket"))) {6             //如果没有的ticket参数,查看是否是退出请求7             if (handler.isLogoutRequest(request)) {8                 if (this.sessionMappingStorage != null && !this.sessionMappingStorage.getClass().equals(HashMapBackedSessionMappingStorage.class)) {9                     //是退出请求,直接销毁session,直接return,不会在执行其他过滤器
10                     handler.destroySession(request, response);
11                     return;
12                 }
13             this.log.trace("Ignoring URI " + request.getRequestURI());
14         } else {
15             handler.recordSession(request);
16         }
17         ///继续执行下一个执行器
18         filterChain.doFilter(servletRequest, servletResponse);
19     }   
AuthenticationFilter,该过滤器主要做法:
 1 public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {2         String requestedUrl = ((HttpServletRequest)servletRequest).getServletPath();3         boolean isExcludedUrl = false;4         //这里会获取到xml中的排除需要过滤的URL配置5         if (this.excludedRequestUrlPatterns != null && this.excludedRequestUrlPatterns.length > 0) {6             Pattern[] arr$ = this.excludedRequestUrlPatterns;7             int len$ = arr$.length;8 9             for(int i$ = 0; i$ < len$; ++i$) {
10                 Pattern p = arr$[i$];
11                 if (isExcludedUrl = p.matcher(requestedUrl).matches()) {
12                     break;
13                 }
14             }
15         }
16 
17         HttpServletRequest request = (HttpServletRequest)servletRequest;
18         HttpServletResponse response = (HttpServletResponse)servletResponse;
19         //如果当前URL是被排除,不需要校验cas单点登录的话,直接跳过当前过滤器,进行下一步
20         if (this.isIgnoreSSO() && isExcludedUrl) {
21             filterChain.doFilter(request, response);
22         } else {
23             //如果当前不被排除在外,查看白名单URL,也可以直接跳过该过滤器
24             boolean isWhiteUrl = false;
25             if (this.whiteRequestUrlPatterns != null && this.whiteRequestUrlPatterns.length > 0) {
26                 Pattern[] arr$ = this.whiteRequestUrlPatterns;
27                 int len$ = arr$.length;
28 
29                 for(int i$ = 0; i$ < len$; ++i$) {
30                     Pattern p = arr$[i$];
31                     if (isWhiteUrl = p.matcher(requestedUrl).matches()) {
32                         break;
33                     }
34                 }
35             }
36 
37             if (isWhiteUrl) {
38                 filterChain.doFilter(request, response);
39             } else {
40                 //如果都没匹配上,说明该URL是需要进行校验查看的
41                 HttpSession session = request.getSession(false);
42                 //从session中取出改属性值,查看当前session是否已经认证过了。如果认证过了了,可以跳过该过滤器
43                 Assertion assertion = session != null ? (Assertion)session.getAttribute("_const_cas_assertion_") : null;
44                 //第一次请求的时候,改对象一定为null,因为没人登录过
45                 if (assertion != null) {
46                     filterChain.doFilter(request, response);
47                 } else {
48                     String serviceUrl = this.constructServiceUrl(request, response);
49                     String ticket = CommonUtils.safeGetParameter(request, this.getArtifactParameterName());
50                     //查看是否session中有_const_cas_gateway_该属性值,第一次登录也没有
51                     boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
52                     //如果都没有
53                     if (!CommonUtils.isNotBlank(ticket) && !wasGatewayed) {
54                         String encodedService;
55                         //查看是否是cas服务器return回调我们的这个接口请求,该属性值在下面,也就是第一次登录的时候,设置的
56                         if (request.getSession().getAttribute("casreturn") != null) {
57                             request.getSession().removeAttribute("casreturn");
58                             if (isExcludedUrl) {
59                                 filterChain.doFilter(request, response);
60                             } else {
61                                 encodedService = Base64.encodeBase64String(serviceUrl.getBytes());
62                                 encodedService = encodedService.replaceAll("[\\s*\t\n\r]", "");
63                                 if (!this.SSOLoginUrl.startsWith("https://") && !this.SSOLoginUrl.startsWith("http://")) {
64                                     this.SSOLoginUrl = this.getServerName() + (this.getServerName().endsWith("/") ? "" : "/") + this.SSOLoginUrl;
65                                 }
66                                 //-------------@这里----------------------
67                                 //一直以为是所有校验都没有参数后,在下面才是跳转到登录页,,没想到,直接回调了,并没有让用户去登陆,而是在这里才去调用登录页
68                                 //让用户去登陆。大坑
69                                 response.sendRedirect(CommonUtils.joinUrl(this.SSOLoginUrl, "nextpage=" + encodedService));
70                             }
71                         } else {
72                             //第一次登录的时候是这里,他会将你xml中的cas服务器地址拼接成login登录地址,我们当前请求的URL编码之后,会被cas登录成功后回调使用
73                             encodedService = this.SSOServerUrl + "/login?service=" + URLEncoder.encode(serviceUrl, "UTF-8") + "&redirect=true";
74                             //并且设置cas服务器回调标识
75                             request.getSession().setAttribute("casreturn", true);
76                             //第一次登录的时候,只能到这里了,因为ticket参数,或则session中_const_cas_assertion_属性都没有,只能去cas服务器请求登录,
77                             //这里有个坑,,没想到在这里没有直接出现登录页,而是调用cas服务器地址后,直接返回来了,而且会在@那里再去调用登录地址
78                             response.sendRedirect(encodedService);
79                             //其他的事情后续就不要再debug了,已经跟我们cas没有啥关系了,博主,debug了半天越看越懵,才发现是服务在做其他的事情,
80                             // 我们的登录页面早就已经出现了
81                         }
82                     } else {
83                         filterChain.doFilter(request, response);
84                     }
85                 }
86             }
87         }
88     }

上面的还有一个坑,就是,在用户登录成功后,回调我们的地址,第一次并不会带给我们ticket参数,而且还会走

ncodedService = this.SSOServerUrl + "/login?service=" + URLEncoder.encode(serviceUrl, "UTF-8") + "&redirect=true";
这个逻辑,并且附上casreturn属性,然后,cas服务器这回才会把ticket参数返回给我们的接口,剩下的就是下一个过滤器的事情了,慢慢来:

好了,这次有ticket了,我们来看下一个过滤器SSO Ticket Validation Filter

 1 public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {2         //这里做了点事,是否为代理,博主没用这个,默认代理为null,返回true3         if (this.preFilter(servletRequest, servletResponse, filterChain)) {4             HttpServletRequest request = (HttpServletRequest)servletRequest;5             HttpServletResponse response = (HttpServletResponse)servletResponse;6             //获取ticket请求参数7             String ticket = CommonUtils.safeGetParameter(request, this.getArtifactParameterName());8             //到这里了,分为三种情况,9             //有ticket,因为你已经登录了,cas服务器登录成功返回给你了,接下来进行校验
10             //无ticket,可能你没有配置第一个过滤器,溜进来了
11             //无ticket,ticket已经校验成功后跳转回来了,用户属性已经设置到session中了,所以这次请求没有ticket了,不用去校验
12             if (CommonUtils.isNotBlank(ticket)) {
13                 if (this.log.isDebugEnabled()) {
14                     this.log.debug("Attempting to validate ticket: " + ticket);
15                 }
16 
17                 try {
18                     //开始ticket票据校验,这才是这个ticket过滤器真正要做的
19                     //constructServiceUrl这个方法不用管,就是拼接一下URL路径,把我的APPID啥的拼接上去
20                     //validate做了挺多事,请看下一个类注释,这里先过去(大概逻辑就是去cas服务器验证ticket)
21                     Assertion assertion = this.ticketValidator.validate(ticket, this.constructServiceUrl(request, response));
22                     if (this.log.isDebugEnabled()) {
23                         this.log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());
24                     }
25                     //看到这里没有,就是在第一个过滤器进行校验的参数,如果ticket验证成功,就会往request,及session设置属性,该属性就是_const_cas_assertion_
26                     //该属性值则是一个用户信息map
27                     request.setAttribute("_const_cas_assertion_", assertion);
28                     if (this.useSession) {
29                         request.getSession().setAttribute("_const_cas_assertion_", assertion);
30                     }
31                     //空方法,不用管
32                     this.onSuccessfulValidation(request, response, assertion);
33                     //ticket验证成功后,在进行跳转,这次是跳到我们自己的请求地址
34                     if (this.redirectAfterValidation) {
35                         this.log.debug("Redirecting after successful ticket validation.");
36                         response.sendRedirect(this.constructServiceUrl(request, response));
37                         return;
38                     }
39                 } catch (TicketValidationException var8) {
40                     response.setStatus(403);
41                     this.log.warn(var8, var8);
42                     this.onFailedValidation(request, response);
43                     if (this.exceptionOnValidationFailure) {
44                         throw new ServletException(var8);
45                     }
46 
47                     return;
48                 }
49             }
50 
51             filterChain.doFilter(request, response);
52         }
53     }

里面的ticket验证逻辑在此:

 1 public Assertion validate(String ticket, String service) throws TicketValidationException {2         //此处是拼接好要调用的URL3         //http://sso.jxeduyun.com/sso/,该路径是在web.xml中改ticket过滤器进行配置的SSOServerUrlPrefix4         //http://sso.jxeduyun.com/sso/serviceValidate?needAttribute=true&ticket=ST-28699-qdyblKpRwc5LpLk57dRM-sso.jxeduyun.com&service=http%3A%2F%2F127.0.0.1%3A9000%2Fdsideal_yy%2FdsTyrzLogin%2FssoLogin%3FloginType%3Dweb%26from%3Dew%26appId%3D00000&appKey=000005         String validationUrl = this.constructValidationUrl(ticket, service);6         if (this.log.isDebugEnabled()) {7             this.log.debug("Constructing validation url: " + validationUrl);8         }9 
10         try {
11             this.log.debug("Retrieving response from server.");
12             //这里不用看,就是发起请求调用上面的接口,查看ticket有效性
13             String serverResponse = this.retrieveResponseFromServer(new URL(validationUrl), ticket);
14             if (serverResponse == null) {
15                 throw new TicketValidationException("The CAS server returned no response.");
16             } else {
17                 if (this.log.isDebugEnabled()) {
18                     this.log.debug("Server response: " + serverResponse);
19                 }
20                 //这个不用看了,就是解析返回的cas数据,然后获取里面的用户信息,并封装成map
21                 return this.parseResponseFromServer(serverResponse);
22             }
23         } catch (MalformedURLException var5) {
24             throw new TicketValidationException(var5);
25         }
26     }

因为ticket验证成功后并没有直接到下一个过滤器,而是从新请求了一次,这次不会有ticket参数了,因为session中已经有属性了,就在前几个过滤器中进行判断,在都走一次,然后才会到下面这个过滤器

 1 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {2         HttpServletRequest request = (HttpServletRequest)servletRequest;3         HttpSession session = request.getSession(false);4         Assertion assertion = (Assertion)((Assertion)(session == null ? request.getAttribute("_const_cas_assertion_") : session.getAttribute("_const_cas_assertion_")));5 6         try {7             //该过滤器的作用就是,把用户对象从session中拿出来,放到AssertionHolder里面,从而在代码中获取对象信息的时候,8             //直接调用该对象即可9             AssertionHolder.setAssertion(assertion);
10             filterChain.doFilter(servletRequest, servletResponse);
11         } finally {
12             AssertionHolder.clear();
13         }
14 
15     }

至此,cas的登录流程全部走完,不知道大家看懂多少,花了博主大概一天的时间才把源码理解通,ticket返回示例给大家一下,还有代码调用:

 1 失败示例:2 <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>3   <cas:authenticationFailure code='INVALID_TICKET'>4     ticket &#039;ST-28699-qdyblKpRwc5LpLk57dRM-sso.jxeduyun.com&#039; not recognized5   </cas:authenticationFailure>6 </cas:serviceResponse>7 成功示例:8 <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>9   <cas:authenticationSuccess>
10     <cas:user>test</cas:user>
11             <cas:attributes>
12                     <cas:multipleId>test-test-test-test-test</cas:multipleId>
13                 
14                     <cas:userId>test</cas:userId>
15                 
16                     <cas:loginName>test</cas:loginName>
17                 
18             </cas:attributes>
19   </cas:authenticationSuccess>
20 </cas:serviceResponse>

代码调用示例:

1         Assertion assertion = AssertionHolder.getAssertion();
2         String openId = assertion.getPrincipal().getName();
3         Map<String, Object> attributes = assertion.getPrincipal().getAttributes();
4         String userId = attributes.get("userId").toString();
5         String loginName = attributes.get("loginName").toString();
6         System.out.println("openId:"+openId);
7         System.out.println("userId:"+userId);
8         System.out.println("loginName:"+loginName);

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

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

相关文章

Spring-bean

Spring 网站&#xff1a;spring.io 两个方面&#xff1a; 简化开发&#xff1a; IoCAOP 框架整合&#xff1a; MyBatis SpringFrameWork系统架构&#xff08;上层依赖下层&#xff09; 解决问题&#xff08;代码耦合度高——模块与模块之间的依赖程度&#xff09; 目标&am…

Pikachu靶场--越权漏洞

参考借鉴 pikachu之越权漏洞_pikachu越权漏洞-CSDN博客 水平越权 需要输入username和password进行登录 查看提示&#xff0c;获取username和password 输入其中一组账号信息进行登录 可以查看到个人信息 在URL中更改username的值-->回车 成功越权&#xff0c;登录到其他账号…

【文献及模型、制图分享】1985-2015年美国坦帕湾流域土地开发利用强度时空变化分析

公众号新功能 目前公众号新增以下等功能 1、处理GIS出图、Python制图、区位图、土地利用现状图、土地利用动态度和重心迁移图等等 2、核密度分析、网络od分析、地形分析、空间分析等等 3、地理加权回归、地理探测器、生态环境质量指数、地理加权回归模型影响因素分析、计算…

[极客大挑战 2020]Roamphp2-Myblog

又来喽 经过一番测试&#xff0c;发现文件包含&#xff0c;使用伪协议读取文件 例&#xff1a;php://filter/readconvert.base64-encode/resourcelogin //这里我只写php部分 //login.php <?php require_once("secret.php"); mt_srand($secret_seed); $_SESSION…

FPGA国内”薪“赛道-在医疗领域的应用

mian 免 ze 责 sheng 声 ming 明 以下观点仅代表个人观点&#xff0c;不代表任何公司或者行业 从下游应用市场来看&#xff0c;通信和工业市场份额位居FPGA芯片一二位&#xff0c;同时通信市场份额有望持续提升。但是目前通信和工业市场趋于稳定&#xff0c;FPGA厂商一直推AI市…

SpringBoot 实现RequestBodyAdvice封装统一接受类功能

一、相关往期文章 SpringBootVue实现AOP系统日志功能_aop的vue完整项目 Spring AOP (面向切面编程&#xff09;原理与代理模式—实例演示_面向切面aop原理详解 二、需求分析 按照一般情况&#xff0c;统一接受类可以像以下的方式进行处理&#xff1a; 如果不想使用 Request…

Vue75-路由传参3

一、在index.js中使用props参数 1-1、写法一&#xff1a;值为对象 此时&#xff0c;参数是固定写死的&#xff0c;不推荐&#xff01; 1-2、值为布尔值 此时只能收到params中的参数&#xff01; 1-3、值为函数 &#xff08;最强大&#xff09; 二、小结

火车头采集器Typecho采集发布模块插件

火车头采集器发布数据到Typecho系统网站应该怎么操作&#xff1f; 1. 火车头采集器Typecho采集发布插件下载安装&#xff1a; 火车头采集器Typecho采集发布模块插件下载地址-CSDN 2. 在火车头采集器软件导Typecho采集发布模块插件&#xff1b; 3. 填写Typecho系统文章对应的…

从零开始的Ollama指南:部署私域大模型

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…

跨行业数据资产共享与协同:构建一体化数据共享平台,解锁数据资产潜力,促进多行业数据流通与深度应用,共创数字化转型新篇章,引领行业发展新趋势,开启智慧互联新纪元

一、引言 随着信息技术的飞速发展&#xff0c;数据已成为推动社会进步和经济发展的关键要素。然而&#xff0c;在传统行业领域&#xff0c;数据往往被限制在各自的“孤岛”中&#xff0c;难以实现跨行业的流通与共享。这不仅限制了数据的价值发挥&#xff0c;也阻碍了行业的创…

【Apache Doris】如何实现高并发点查?(原理+实践全析)

【Apache Doris】如何实现高并发点查&#xff1f;&#xff08;原理实践全析&#xff09; 一、背景说明二、原理介绍三、环境信息四、Jmeter初始化五、参数预调六、用例准备七、高并发实测八、影响因素九、总结 本文主要分享 Apache Doris 是如何实现高并发点查的&#xff0c;以…

【pytorch02】手写数字问题引入

1.数据集 现实生活中遇到的问题 车牌识别身份证号码识别快递单的识别 都会涉及到数字识别 MNIST&#xff08;收集了很多人手写的0到9数字的图片&#xff09; 每个数字拥有7000个图像train/test splitting:60k vs 10k 图片大小28 28 数据集划分成训练集和测试集合的意义…

推荐4款电脑软件,简单已入手,关键是免费,建议收藏

拖把更名器 拖把更名器是一款功能强大的文件名称修改工具&#xff0c;主要用于批量进行文件更名和整理音乐文件标签。该软件结合资源管理器右键菜单&#xff0c;支持多种文件格式和操作方式&#xff0c;包括MP3、RM、RMVB、WMA等标签更名&#xff0c;文件名、标签内码转换、繁简…

threeJS 基础 03---动画

1.动画效果渲染循环 注&#xff1a; 使用循环渲染时&#xff0c;不用手动渲染到画布且再次调用监听更新事件&#xff0c;两者只用使用其中之一即可 周期循环&#xff0c;默认理想状态下每秒循环60次 requestAnimationFrame 渲染帧率&#xff08;详情见threeJs的文档&#xff…

五种主流数据库连接池的比较和分析(从零入门)

数据库连接池&#xff08;Database Connection Pool&#xff09;是现代应用程序中至关重要的组件。它通过管理一组数据库连接的复用&#xff0c;极大地提升了应用程序的性能和效率。在没有连接池的情况下&#xff0c;每个数据库请求都需要打开和关闭数据库连接&#xff0c;这不…

Python编辑器pycharm详细安装步骤

PyCharm 的详细安装步骤 以下是在 Windows 系统上安装 PyCharm 的详细步骤&#xff1a; 第一步&#xff1a;下载安装程序 访问 PyCharm 官方网站&#xff08;https://www.jetbrains.com/pycharm/&#xff09;&#xff0c;根据自己的需求选择社区版&#xff08;Community&…

内容安全复习 6 - 白帽子安全漏洞挖掘披露的法律风险

文章目录 安全漏洞的法律概念界定安全漏洞特征白帽子安全漏洞挖掘面临的法律风险“白帽子”安全漏洞挖掘的风险根源“白帽子”的主体边界授权行为边界关键结论 安全漏洞的法律概念界定 可以被利用来破坏所在系统的网络或信息安全的缺陷或错误&#xff1b;被利用的网络缺陷、错…

车辆轨迹预测系列 (三):nuScenes数据集详细介绍-1

车辆轨迹预测系列 (三)&#xff1a;nuScenes数据集详细介绍-1 文章目录 车辆轨迹预测系列 (三)&#xff1a;nuScenes数据集详细介绍-1一、数据集准备1、解压2、安装nuscenes-devkit3、介绍 二、架构内容解释1、category 类别2、attribute 属性3、visibility 可见性4、instance …

通讯协议大全(UART,RS485,SPI,IIC)

参考自&#xff1a; 常见的通讯协议总结&#xff08;USART、IIC、SPI、485、CAN&#xff09;-CSDN博客 UART那么好用&#xff0c;为什么单片机还需要I2C和SPI&#xff1f;_哔哩哔哩_bilibili 5分钟看懂!串口RS232 RS485最本质的区别&#xff01;_哔哩哔哩_bilibili 喜欢几位…

私域电商新纪元:消费增值模式的创新与成功实践

大家好&#xff0c;我是吴军&#xff0c;很高兴能够与您分享私域电商领域的魅力与机遇。今天&#xff0c;我将为大家呈现一个令人瞩目的成功案例&#xff0c;这个案例充分展现了私域电商的巨大潜力和无限可能。 在短短一个月的时间里&#xff0c;我们的客户成功实现了业绩的飞跃…