问题1:什么是shiro?它有什么用? 答:shiro是apache公司推出的一款安全框架,主要在项目中进行权限控制
核心概念
@@@@@@@shiro中的几个核心概念: 1、SecurityManager:安全管理器 作用:用于执行认证(登录)、授权(获得用户的访问权限) 2、Subject:主体 作用:它代表当前用户 3、Realm:领域对象 作用:它用于封装认证、授权的方法
基本语法
阶段1:讲解shiro的基本语法 (java程序即可) 1、基于ini文件的认证(登录)--把用户名和密码以文件的形式保存以后,用来验证 2、基于realm类的认证----用户名和密码存放在数据库中,连接数据库来验证 3、md5加密---防的是管理员 4、基于ini文件的授权----是在ini文件中获取,用来判断用户拥有哪种角色和权限 5、基于realm类的授权----在数据库中获取,来判断
1、基于ini文件的认证
/*首先安装一个Ini的插件*/
shiro的基本语法-----基于ini文件的认证(登录)
1、创建工程
2、导入下列依赖
1、shiro-core
2、commons-logging
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
3、在resources目录下,创建一个ini文件,用于封装用户信息
#配置用户信息
[users]
#用户名=密码
jack=111
andy=222
4、编写测试类进行测试
----------------------------------------------------------------------------------
@@@@@@@在实际应用中,我们不可能将用户名密码写在ini文件中,这样不安全,这些信息都是存放在数据库中的
测视类
package org.java.demo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
/**
* @author arjun
* @title: iniDemo
* @description: 描述信息
* @date 2023.07.12 18:59
*/
//基于ini文件的认证
public class iniDemo {
public static void main(String[] args) {
//1、获得一个工厂类,用于产生安全管理器securityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2、创建安全管理器securityManager
SecurityManager securityManager = factory.getInstance();
//3、将安全管理器设置到当前运行环境中
SecurityUtils.setSecurityManager(securityManager);
//4、获得主体subject(代表当前用户),用于执行认证操作
Subject subject = SecurityUtils.getSubject();
//5、创建令牌token,用于封装用户名及密码
UsernamePasswordToken token = new UsernamePasswordToken("jack","111");
try{
//6、用户登录,如果登录失败将会产生异常
subject.login(token);
//7、判断用户是否登录
if(subject.isAuthenticated()){
//返回true,表示用户已登录
System.out.println("用户登录成功!");
}
}catch(UnknownAccountException ex){
System.out.println("错误:用户名不存在,登录失败");
}catch (IncorrectCredentialsException ex){
System.out.println("错误:密码错误,登录失败");
}
}
}
2、基于realm类的认证
@@@@@@@基于realm类的认证
1、编写AuthcRealm类(领域对象,封装认证、授权的方法)
public class AuthcRealm extends AuthorizingRealm
2、重写父类的中两个抽象方法
public class AuthcRealm extends AuthorizingRealm {
//授权的方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
//认证的方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//从令牌中获得用户信息(用户名)
String principal = (String) token.getPrincipal();
//根据用户名到数据库中判断,用户名是否存在
//此处,模拟数据库操作,如果是jack我们就认为当前用户不存在
if(principal.equals("jack")){
return null;//表示用户名不存在
}
//用户名存在,从数据库获得当前用户的正确密码
String pwd = "123";
//创建一个AuthenticationInfo对象,封装认证的用户信息
/**
* 参数1:用户信息
* 参数2:当前用户在数据库对应的密码
* 参数3:realm类的别名,可以任意指定
*/
AuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd,"myRealm");
return info;
}
}
3、配置shiro2.ini文件用于配置reaml
[main]
#定义别名,指向Realm
myRealm=org.java.realms.AuthcRealm
#设置安全管理器采用哪一个Realm类进行认证
securityManager.realm=$myRealm
4、编写测试类(测视类同上,只改变引用的文件名--shiro2.ini)
//1、获得一个工厂类,用于产生安全管理器securityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro2.ini");
...
3、MD5加密
@@@@@@@@@@@@MD5加密
在实际应用中,一般用户名,密码都是存在数据库中的,对于系统管理员而言,它是可以看到所有用户的用户名,密码
但是这样就非常不安全。为了解决该问题,在开发中,用户名会直接存放到数据库,但密码将会采用MD5加密后,再存放到数据库中
此时,系统管理员看到的密码将会是加密的密码,它并不是真正的密码,并不能直接使用
加密示例
//MD5加密示例类
public class md5Demo {
public static void main(String[] args) {
//原始密码
String pwd="123";
//指定盐,也就是混合在加密算法的最后数据--利用uuid随机生成盐
String salt = UUID.randomUUID().toString();
System.out.println("混合参数:"+salt);
//指定加密次数
int count=new Random().nextInt(10);
System.out.println("加密次数 :"+count);
//MD5 加密
Md5Hash md5Hash = new Md5Hash(pwd,salt, count);
System.out.println("加密后:"+md5Hash.toString());
}
}
基于realm认证的md5加密
@@@@@@@@@@@基于Realm类进行认证时,采用MD5加密
1、在shiro2.ini文件中指定凭证匹配器用于设置加密方式以及加密次数
#指定凭证匹配器(指定加密规则)
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#指定加密方式
credentialsMatcher.hashAlgorithmName=md5
#指定散列次数(加密次数)
credentialsMatcher.hashIterations=3
2、在shiro2.ini文件中指开realm,并且设置realm采用哪一种凭证匹配器
#定义一个变量,指向realm类
myRealm=org.java.reamls.MyRealm
#指定当前的myRealm类,采用哪一种凭证匹配器,对密码加密
myRealm.credentialsMatcher=$credentialsMatcher
#指定安全管理器SecurityManager通过哪一个Realm进行认证
securityManager.realm=$myRealm
3、在Realm类中认证中的方法中,设置从数据库中查询到的加密后的正确密码以及加密用的盐
/**
* 参数1:用户信息
* 参数2:当前用户在数据库对应的密码
* 参数3:对用户输入的密码加密用的盐
* 参数4:realm类的别名,可以任意指定
*/
//设置加密用的盐
String salt ="accp";
AuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd, ByteSource.Util.bytes(salt),"myRealm");
4、基于ini文件授权
授权:指认证成功后在进行权限、角色判断时,得到用户的角色或者是访问权限
1、基于ini文件的授权
指:将用户的信息、角色、权限写在一个ini文件中
role-----------角色
authorization--授权
permission-----权限
power----------权力
1、编写shiro3.ini文件,在文件中编写如下代码
[users]
#用户名=密码,角色
jack=111,role1
andy=111,role1,role2
tom=111,role3
chris=111,role4
[roles]
#指定角色及权限信息
role1=user:add,user:query
role2=user:del,user:update
role3=user:*
role4=*:*
2、编写测试类进行测试
//进行角色判断
//判断用户是否拥有某一种角色
if(subject.hasRole("role2")){
System.out.println("有权限访问.....");
}else{
System.out.println("无权限访问....");
}
//判断用户是否拥有某一种访问权限
if(subject.isPermitted("user:add")){
System.out.println("有权限访问.....");
}else{
System.out.println("无权限访问....");
}
//判断用户是拥有多种访问权限
if(subject.isPermittedAll("user:add","user:del","user:query")){
System.out.println("有权限访问.....");
}else{
System.out.println("无权限访问....");
}
5、基于realm类授权
@@@@@@@@@@@@@@@@@@@@@@基于Realm类的权限判断
1、编写shiro4.ini文件
[main]
#指定凭证匹配器(指定加密规则)
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#指定加密方式
credentialsMatcher.hashAlgorithmName=md5
#指定散列次数(加密次数)
credentialsMatcher.hashIterations=3
#定义一个变量,指向realm类
myRealm=org.java.realms.AuthcRealm
#指定当前的myRealm类,采用哪一种凭证匹配器,对密码加密
myRealm.credentialsMatcher=$credentialsMatcher
#指定安全管理器SecurityManager通过哪一个Realm进行认证
securityManager.realm=$myRealm
2、修改Realm类授权的方法
@@@@@@@@默认情况下,只有进行权限或者角色判断时,才会执行授权的方法
//授权的方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//从PrincipalCollection获得用户信息(也就是认证方法返回的AuthenticationInfo对象中的第一个参数)
String principal = (String) principals.getPrimaryPrincipal();
//根据用户信息从数据库查询用户的角色或者是访问权限
// List<String> roles = new ArrayList<>();
// roles.add("role1");
// roles.add("role2");
//
// //创建AuthorizationInfo用于封装用户角色或者访问权限
// SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// //指定角色
// info.addRoles(roles);
//到数据库中查询访问权限
List<String> list = new ArrayList<>();
list.add("user:add");
list.add("user:del");
//创建AuthorizationInfo用于封装用户角色或者访问权限
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//指定访问权限
info.addStringPermissions(list);
return info;
}
第二章
shiro综合案例
阶段1:搭建基本结构(与shiro无关)
阶段2:加入shrio
阶段3:基于shiro的认证(与数据库无关)
阶段4:连接数据库进行认证
阶段5: 得到访问权限,根据权限加载对应的菜单
阶段6:加入缓存,将权限进行缓存
阶段1:基本结构
1、创建web应用
2、导入依赖(ssm用到依赖)
3、导入log4j.properties,db.properties,mybatis-config.xml
4、编写applicationContext.xml
5、web.xml
6、编写index.jsp
7、编写FirstController
8、编写main.jsp
依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-version>5.1.6.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- spring相关的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.1_3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 数据源及连接池相关的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!-- web应关的依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
<!-- shiro的相关依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.6</version>
</dependency>
</dependencies>
阶段2:加入shiro
1、加入依赖
1、加入依赖
shiro-core
shiro-web
shiro-spring
shiro-ehcache
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.6</version>
</dependency>
2、编写web.xml
2、编写web.xml文件,配置shiro
<!--指定监听器要加载的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<!-- 配置shiro的过滤器-->
<filter>
<filter-name>shiro</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<!--配置属性1,用于指定spring管理shiro的生命周期-->
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<!-- 配置属性2,用于指定在spring配置文件中注册的shiro过滤器的名称 -->
<init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiro</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置监听器,加入载所有的配置文件-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3、shiro配置
3、编写applicationContext-shiro.xml文件,用于进行shiro配置
4、authcrealm连接数据库
4、编写AuthcRealm用于指定认证、授权的方法
public class AuthcRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
return null;
}
}
5、修改shiro配置
5、修改applicationContext-shiro.xml文件,用于进行shiro配置
<!-- 注册SHIRO过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--指定要使用的安全管理器-->
<property name="securityManager" ref="securityManager"/>
<!--指定如果当前用户未登录,通过哪一个请求地址进入到登录界面-->
<property name="loginUrl" value="/login.do"/>
<!--指定shiro过滤品拦截请求的规则-->
<!--
/**=anon 它表示所有请求的资源允许匿名访问,不登录也可以访问的
/**=authc 它表示所有请求的资源必须登录后才能访问
-->
<property name="filterChainDefinitions">
<value>
/js/**=anon
/css/**=anon
/img/**=anon
/favicon.ico =anon
/**=authc
</value>
</property>
</bean>
<!-- 注册安全管理器securityManager-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="authcRealm"/>
</bean>
<!-- 注册realm-->
<bean id="authcRealm" class="org.java.reamls.AuthcRealm"/>
6、编写控制器类
6、编写LoginController控制器类
@Controller
/***
* 该控制器类只有两种情况下会进入
* 1 用户未登录时,请求被拦截,会进入.会通过当前类进入到登录界面
* 2 如果信息错误,登录失败时,也会进入当前控制器类
*
* 如果是正常登录,请求不进入该控制器类的
*/
public class LoginController {
@RequestMapping("/login")
public String login(){
//跳转到登录界面
return "/login";
}
}
7、login.jsp
7、编写login.jsp页面,编写登录的表单
注意:用户名必须是:username,密码必须是password
<form action="/login.do" method="post">
姓名:<input type="text" name="username"/><Br>
密码:<input type="password" name="password"/><Br>
<input type="submit" value="登录">
</form>
8、编写realm类
8、编写reaml类的代码,执行认证
@@@@如果认证成功就会执行之前未执行的请求
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获得用户信息
String principal = (String) token.getPrincipal();
//到数据库中判断用户名是否存在
if(principal.equals("jack")){
return null;
}
//得到当前用户的正确密码
String pwd = "123";
AuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd,"myRealm");
return info;
}
9、出现错误
@@@@@@@@登录成功后,可以会出现下列错误:
HTTP Status 404 - /favicon.ico
原因是浏览器找不到图标,解决方案是:
@@@@@shiro登录成功以后,如果显示favicon.ico错误,原因是:
shiro它会访问一个图标,如果图标无法访问将会导致该错误信息
解决方案:
1、在shiroFilter中配置,该图标允许匿名访问
/favicon.ico = anon
2、在web.xml文件中进行如下配置
<mime-mapping>
<extension>ico</extension>
<mime-type>image/x-icon</mime-type>
</mime-mapping>
第三章
阶段3:shiro认证
1、在LoginController中编写对应的代码
@@@@如果未登录,就转向登录界面,如果是登录失败,就抛出异常
@Controller
/***
* 该控制器类只有两种情况下会进入
* 1 用户未登录时,请求被拦截,会进入.会通过当前类进入到登录界面
* 2 如果信息错误,登录失败时,也会进入当前控制器类
*
* 如果是正常登录,请求不进入该控制器类的
*/
public class LoginController {
/**
* 请求只有两种情况进入该控制器
* 1、未登录
* 2、登录失败
* 如果是因为登录失败进入的,请求中request将会携带一个名为shiroLoginFailure的参数,
* 如果是因为未登录进入的,该参数为null
* @return
*/
@RequestMapping("/login")
public String login(HttpServletRequest request){
//从请求中获得参数shiroLoginFailure,用于判断是未登录进入还是登录失败进入
String msg = (String) request.getAttribute("shiroLoginFailure");
System.out.println(msg);
if(msg!=null){
//登录失败进入的
//判断登录失败的原因
if(msg.endsWith("UnknownAccountException")){
throw new RuntimeException("用户名不存在!");
}
if(msg.endsWith("IncorrectCredentialsException")){
throw new RuntimeException("密码错误!");
}
}
//如果是未登录进入的,就转向跳转到登录界面
return "/login";
}
}
2、编写异常处理类,处理异常
@Component
public class ShiroException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//获得异常原因
String msg = e.getMessage();
//获得modelandView
ModelAndView mv = new ModelAndView("/err");
//存放异常原因
mv.addObject("msg",msg);
return mv;
}
}
3、编写异常显示页面err.jsp
<h1>登录失败,原因是:${requestScope.msg}</h1>
<A href="index.jsp">返回</A>
4、编写FirstController的代码。指定登录成功后要执行的操作
@Controller
public class FirstController {
@RequestMapping("/first")
public String first(HttpSession session){
//获得登录成功的主体subject
Subject subject = SecurityUtils.getSubject();
//从主体中获得认证用户信息(即为Realm类认证方法返回的第一个参数)
String principal = (String) subject.getPrincipal();
## 最后
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/b50c0755e5a3c1e5c4bc90f84cf5cf42.png)
![img](https://img-blog.csdnimg.cn/img_convert/cfa17c6f16a6c3f173cd897857f4217f.png)
![img](https://img-blog.csdnimg.cn/img_convert/043982b7eb3917ce4e3a0a01c677f390.png)
![img](https://img-blog.csdnimg.cn/img_convert/d38052b6554e930b8eec70d373020a7e.png)
![img](https://img-blog.csdnimg.cn/img_convert/f202c585231241e83a26fa691d3cbdab.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**
[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)
**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
``
4、编写FirstController的代码。指定登录成功后要执行的操作
@Controller
public class FirstController {
@RequestMapping(“/first”)
public String first(HttpSession session){
//获得登录成功的主体subject
Subject subject = SecurityUtils.getSubject();
//从主体中获得认证用户信息(即为Realm类认证方法返回的第一个参数)
String principal = (String) subject.getPrincipal();
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-h8bgizuZ-1715565752420)]
[外链图片转存中…(img-GjQPAwzh-1715565752420)]
[外链图片转存中…(img-njysricg-1715565752420)]
[外链图片转存中…(img-j3IhEiM9-1715565752421)]
[外链图片转存中…(img-9EFTT13i-1715565752421)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!