Spring Boot(十四):spring boot整合shiro-登錄認證和權限管理

Spring Boot(十四):spring boot整合shiro-登錄認證和權限管理

使用Spring Boot集成Apache Shiro。安全應該是互聯網公司的一道生命線,幾乎任何的公司都會涉及到這方面的需求。在Java領域一般有Spring Security、Apache Shiro等安全框架,但是由于Spring Security過于龐大和復雜,大多數公司會選擇Apache Shiro來使用,這篇文章會先介紹一下Apache Shiro,在結合Spring Boot給出使用案例。

一、Apache Shiro

1,What is Apache Shiro?

Apache Shiro是一個功能強大、靈活的,開源的安全框架。它可以干凈利落地處理身份驗證、授權、企業會話管理和加密。

Apache Shiro的首要目標是易于使用和理解。安全通常很復雜,甚至讓人感到很痛苦,但是Shiro卻不是這樣子的。一個好的安全框架應該屏蔽復雜性,向外暴露簡單、直觀的API,來簡化開發人員實現應用程序安全所花費的時間和精力。

Shiro能做什么呢?

  • 驗證用戶身份
  • 用戶訪問權限控制,比如:1、判斷用戶是否分配了一定的安全角色。2、判斷用戶是否被授予完成某個操作的權限
  • 在非 web 或 EJB 容器的環境下可以任意使用Session API
  • 可以響應認證、訪問控制,或者 Session 生命周期中發生的事件
  • 可將一個或以上用戶安全數據源數據組合成一個復合的用戶 “view”(視圖)
  • 支持單點登錄(SSO)功能
  • 支持提供“Remember Me”服務,獲取用戶關聯信息而無需登錄

等等——都集成到一個有凝聚力的易于使用的API。

Shiro 致力在所有應用環境下實現上述功能,小到命令行應用程序,大到企業應用中,而且不需要借助第三方框架、容器、應用服務器等。當然 Shiro 的目的是盡量的融入到這樣的應用環境中去,但也可以在它們之外的任何環境下開箱即用。

2,Apache Shiro Features 特性

Apache Shiro是一個全面的、蘊含豐富功能的安全框架。下圖為描述Shiro功能的框架圖:

Authentication(認證), Authorization(授權), Session Management(會話管理), Cryptography(加密)被 Shiro 框架的開發團隊稱之為應用安全的四大基石。那么就讓我們來看看它們吧:

  • Authentication(認證):用戶身份識別,通常被稱為用戶“登錄”
  • Authorization(授權):訪問控制。比如某個用戶是否具有某個操作的使用權限。
  • Session Management(會話管理):特定于用戶的會話管理,甚至在非web 或 EJB 應用程序。
  • Cryptography(加密):在對數據源使用加密算法加密的同時,保證易于使用。

還有其他的功能來支持和加強這些不同應用環境下安全領域的關注點。特別是對以下的功能支持:

  • Web支持:Shiro 提供的 web 支持 api ,可以很輕松的保護 web 應用程序的安全。
  • 緩存:緩存是 Apache Shiro 保證安全操作快速、高效的重要手段。
  • 并發:Apache Shiro 支持多線程應用程序的并發特性。
  • 測試:支持單元測試和集成測試,確保代碼和預想的一樣安全。
  • “Run As”:這個功能允許用戶假設另一個用戶的身份(在許可的前提下)。
  • “Remember Me”:跨 session 記錄用戶的身份,只有在強制需要時才需要登錄。

注意: Shiro不會去維護用戶、維護權限,這些需要我們自己去設計/提供,然后通過相應的接口注入給Shiro

3,High-Level Overview 高級概述

在概念層,Shiro 架構包含三個主要的理念:Subject,SecurityManager和 Realm。下面的圖展示了這些組件如何相互作用,我們將在下面依次對其進行描述。

  • Subject:當前用戶,Subject 可以是一個人,但也可以是第三方服務、守護進程帳戶、時鐘守護任務或者其它–當前和軟件交互的任何事件。
  • SecurityManager:管理所有Subject,SecurityManager 是 Shiro 架構的核心,配合內部安全組件共同組成安全傘。
  • Realms:用于進行權限信息的驗證,我們自己實現。Realm 本質上是一個特定的安全 DAO:它封裝與數據源連接的細節,得到Shiro 所需的相關的數據。在配置 Shiro 的時候,你必須指定至少一個Realm 來實現認證(authentication)和/或授權(authorization)。

我們需要實現Realms的Authentication 和 Authorization。其中 Authentication 是用來驗證用戶身份,Authorization 是授權訪問控制,用于對用戶進行的操作授權,證明該用戶是否允許進行當前操作,如訪問某個鏈接,某個資源文件等。

二、快速上手

1,基礎信息

(1)pom包依賴

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>net.sourceforge.nekohtml</groupId><artifactId>nekohtml</artifactId><version>1.9.22</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
</dependencies>

重點是 shiro-spring包

(2)配置文件

spring:datasource:url: jdbc:mysql://localhost:3306/test
      username: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverjpa:database: mysqlshow-sql: truehibernate:ddl-auto: updatenaming:strategy: org.hibernate.cfg.DefaultComponentSafeNamingStrategyproperties:hibernate:dialect: org.hibernate.dialect.MySQL5Dialectthymeleaf:cache: falsemode: LEGACYHTML5

thymeleaf的配置是為了去掉html的校驗

(3)頁面

我們新建了六個頁面用來測試:

  • index.html :首頁
  • login.html :登錄頁
  • userInfo.html : 用戶信息頁面
  • userInfoAdd.html :添加用戶頁面
  • userInfoDel.html :刪除用戶頁面
  • 403.html : 沒有權限的頁面

除過登錄頁面其它都很簡單,大概如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>index</h1>
</body>
</html>

2,RBAC

RBAC 是基于角色的訪問控制(Role-Based Access Control )在 RBAC 中,權限與角色相關聯,用戶通過成為適當角色的成員而得到這些角色的權限。這就極大地簡化了權限的管理。這樣管理都是層級相互依賴的,權限賦予給角色,而把角色又賦予用戶,這樣的權限設計很清楚,管理起來很方便。

采用jpa技術來自動生成基礎表格,對應的entity如下:

用戶信息

@Entity
public class UserInfo implements Serializable {@Id@GeneratedValueprivate Integer uid;@Column(unique =true)private String username;//帳號private String name;//名稱(昵稱或者真實姓名,不同系統不同定義)private String password; //密碼;private String salt;//加密密碼的鹽private byte state;//用戶狀態,0:創建未認證(比如沒有激活,沒有輸入驗證碼等等)--等待驗證的用戶 , 1:正常狀態,2:用戶被鎖定.@ManyToMany(fetch= FetchType.EAGER)//立即從數據庫中進行加載數據;@JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })private List<SysRole> roleList;// 一個用戶具有多個角色// 省略 get set 方法}

角色信息

@Entity
public class SysRole {@Id@GeneratedValueprivate Integer id; // 編號private String role; // 角色標識程序中判斷使用,如"admin",這個是唯一的:private String description; // 角色描述,UI界面顯示使用private Boolean available = Boolean.FALSE; // 是否可用,如果不可用將不會添加給用戶//角色 -- 權限關系:多對多關系;@ManyToMany(fetch= FetchType.EAGER)@JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})private List<SysPermission> permissions;// 用戶 - 角色關系定義;
    @ManyToMany@JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")})private List<UserInfo> userInfos;// 一個角色對應多個用戶// 省略 get set 方法}

權限信息

@Entity
public class SysPermission implements Serializable {@Id@GeneratedValueprivate Integer id;//主鍵.private String name;//名稱.@Column(columnDefinition="enum('menu','button')")private String resourceType;//資源類型,[menu|button]private String url;//資源路徑.private String permission; //權限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:viewprivate Long parentId; //父編號private String parentIds; //父編號列表private Boolean available = Boolean.FALSE;@ManyToMany@JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})private List<SysRole> roles;// 省略 get set 方法}

根據以上的代碼會自動生成user_info(用戶信息表)、sys_role(角色表)、sys_permission(權限表)、sys_user_role(用戶角色表)、sys_role_permission(角色權限表)這五張表,為了方便測試我們給這五張表插入一些初始化數據:

INSERT INTO `user_info` (`uid`,`username`,`name`,`password`,`salt`,`state`) VALUES ('1', 'admin', '管理員', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', 0);
INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (1,0,'用戶管理',0,'0/','userInfo:view','menu','userInfo/userList');
INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (2,0,'用戶添加',1,'0/1','userInfo:add','button','userInfo/userAdd');
INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (3,0,'用戶刪除',1,'0/1','userInfo:del','button','userInfo/userDel');
INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (1,0,'管理員','admin');
INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (2,0,'VIP會員','vip');
INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (3,1,'test','test');
INSERT INTO `sys_role_permission` VALUES ('1', '1');
INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (1,1);
INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (2,1);
INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (3,2);
INSERT INTO `sys_user_role` (`role_id`,`uid`) VALUES (1,1);

3,Shiro 配置

首先要配置的是ShiroConfig類,Apache Shiro 核心通過 Filter 來實現,就好像SpringMvc 通過DispachServlet 來主控制一樣。 既然是使用 Filter 一般也就能猜到,是通過URL規則來進行過濾和權限校驗,所以我們需要定義一系列關于URL的規則和訪問權限。

(1)ShiroConfig

@Configuration
public class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {System.out.println("ShiroConfiguration.shirFilter()");ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);//攔截器.Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();// 配置不會被攔截的鏈接 順序判斷filterChainDefinitionMap.put("/static/**", "anon");//配置退出 過濾器,其中的具體的退出代碼Shiro已經替我們實現了filterChainDefinitionMap.put("/logout", "logout");//<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心代碼就不好使了;//<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->filterChainDefinitionMap.put("/**", "authc");// 如果不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面shiroFilterFactoryBean.setLoginUrl("/login");// 登錄成功后要跳轉的鏈接shiroFilterFactoryBean.setSuccessUrl("/index");//未授權界面;shiroFilterFactoryBean.setUnauthorizedUrl("/403");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}@Beanpublic MyShiroRealm myShiroRealm(){MyShiroRealm myShiroRealm = new MyShiroRealm();return myShiroRealm;}@Beanpublic SecurityManager securityManager(){DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();securityManager.setRealm(myShiroRealm());return securityManager;}
}

Filter Chain定義說明:

  • 一個URL可以配置多個Filter,使用逗號分隔
  • 當設置多個過濾器時,全部驗證通過,才視為通過
  • 部分過濾器可指定參數,如perms,roles

Shiro內置的FilterChain

  • anon:所有url都都可以匿名訪問
  • authc: 需要認證才能進行訪問
  • user:配置記住我或認證通過可以訪問

(2)登錄認證實現

在認證、授權內部實現機制中都有提到,最終處理都將交給Real進行處理。因為在Shiro中,最終是通過Realm來獲取應用程序中的用戶、角色及權限信息的。通常情況下,在Realm中會直接從我們的數據源中獲取Shiro需要的驗證信息。可以說,Realm是專用于安全框架的DAO. Shiro的認證過程最終會交由Realm執行,這時會調用Realm的getAuthenticationInfo(token)方法。

該方法主要執行以下操作:

  • 檢查提交的進行認證的令牌信息
  • 根據令牌信息從數據源(通常為數據庫)中獲取用戶信息
  • 對用戶信息進行匹配驗證。
  • 驗證通過將返回一個封裝了用戶信息的AuthenticationInfo實例。
  • 驗證失敗則拋出AuthenticationException異常信息。

而在我們的應用程序中要做的就是自定義一個Realm類,繼承AuthorizingRealm抽象類,重載doGetAuthenticationInfo(),重寫獲取用戶信息的方法。

doGetAuthenticationInfo的重寫:

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {System.out.println("MyShiroRealm.doGetAuthenticationInfo()");//獲取用戶的輸入的賬號.String username = (String)token.getPrincipal();System.out.println(token.getCredentials());//通過username從數據庫中查找 User對象,如果找到,沒找到.//實際項目中,這里可以根據實際情況做緩存,如果不做,Shiro自己也是有時間間隔機制,2分鐘內不會重復執行該方法UserInfo userInfo = userInfoService.findByUsername(username);System.out.println("----->>userInfo="+userInfo);if(userInfo == null){return null;}SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userInfo, //用戶名userInfo.getPassword(), //密碼ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+saltgetName()  //realm name
    );return authenticationInfo;
}

(3)鏈接權限的實現

shiro的權限授權是通過繼承AuthorizingRealm抽象類,重載doGetAuthorizationInfo();當訪問到頁面的時候,鏈接配置了相應的權限或者shiro標簽才會執行此方法否則不會執行,所以如果只是簡單的身份認證沒有權限的控制的話,那么這個方法可以不進行實現,直接返回null即可。在這個方法中主要是使用類:SimpleAuthorizationInfo進行角色的添加和權限的添加。

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {System.out.println("權限配置-->MyShiroRealm.doGetAuthorizationInfo()");SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();UserInfo userInfo  = (UserInfo)principals.getPrimaryPrincipal();for(SysRole role:userInfo.getRoleList()){authorizationInfo.addRole(role.getRole());for(SysPermission p:role.getPermissions()){authorizationInfo.addStringPermission(p.getPermission());}}return authorizationInfo;
}

當然也可以添加set集合:roles是從數據庫查詢的當前用戶的角色,stringPermissions是從數據庫查詢的當前用戶對應的權限:

authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(stringPermissions);

就是說如果在shiro配置文件中添加了filterChainDefinitionMap.put(“/add”, “perms[權限添加]”);就說明訪問/add這個鏈接必須要有“權限添加”這個權限才可以訪問,如果在shiro配置文件中添加了filterChainDefinitionMap.put(“/add”, “roles[100002],perms[權限添加]”);就說明訪問/add這個鏈接必須要有“權限添加”這個權限和具有“100002”這個角色才可以訪問。

(4)登錄實現

登錄過程其實只是處理異常的相關信息,具體的登錄驗證交給shiro來處理:

@RequestMapping("/login")
public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{System.out.println("HomeController.login()");// 登錄失敗從request中獲取shiro處理的異常信息。// shiroLoginFailure:就是shiro異常類的全類名.String exception = (String) request.getAttribute("shiroLoginFailure");System.out.println("exception=" + exception);String msg = "";if (exception != null) {if (UnknownAccountException.class.getName().equals(exception)) {System.out.println("UnknownAccountException -- > 賬號不存在:");msg = "UnknownAccountException -- > 賬號不存在:";} else if (IncorrectCredentialsException.class.getName().equals(exception)) {System.out.println("IncorrectCredentialsException -- > 密碼不正確:");msg = "IncorrectCredentialsException -- > 密碼不正確:";} else if ("kaptchaValidateFailed".equals(exception)) {System.out.println("kaptchaValidateFailed -- > 驗證碼錯誤");msg = "kaptchaValidateFailed -- > 驗證碼錯誤";} else {msg = "else >> "+exception;System.out.println("else -- >" + exception);}}map.put("msg", msg);// 此方法不處理登錄成功,由shiro進行處理return "/login";
}

4,測試

1、編寫好后就可以啟動程序,訪問http://localhost:8080/userInfo/userList頁面,由于沒有登錄就會跳轉到http://localhost:8080/login頁面。登錄之后就會跳轉到index頁面,登錄后,直接在瀏覽器中輸入http://localhost:8080/userInfo/userList訪問就會看到用戶信息。上面這些操作時候觸發MyShiroRealm.doGetAuthenticationInfo()這個方法,也就是登錄認證的方法。

2、登錄admin賬戶,訪問:http://127.0.0.1:8080/userInfo/userAdd顯示用戶添加界面,訪問http://127.0.0.1:8080/userInfo/userDel顯示403沒有權限。上面這些操作時候觸發MyShiroRealm.doGetAuthorizationInfo()這個方面,也就是權限校驗的方法。

3、修改admin不同的權限進行測試

shiro很強大,這僅僅是完成了登錄認證和權限管理這兩個功能,更多內容。

?

轉載于:https://www.cnblogs.com/lizm166/p/10270547.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387594.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387594.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387594.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

通用權限管理系統組件 (GPM - General Permissions Manager) 不改數據庫、甚至不寫代碼就集成銅墻鐵壁權限管理組件...

為什么80%的碼農都做不了架構師&#xff1f;>>> 越成熟的東西&#xff0c;越牛X的東西&#xff0c;越簡單才對&#xff0c;簡單才是硬道理&#xff0c;蘋果的手機只有少數幾個按鍵&#xff0c;蘋果Ipad也很少的按鈕&#xff0c;甚至連蘋果的筆記本鍵盤都少一排&…

數學符號及讀法大全

數學符號及讀法大全 常用數學輸入符號&#xff1a; ≈ ≡ ≠ &#xff1d; ≤≥ &#xff1c; &#xff1e; ≮ ≯ ∷ &#xff0b; &#xff0d; &#xff0f; ∫ ∮ ∝ ∞ ∧ ∨ ∑ ∏ ∪ ∩ ∈ ∵ ∴ ⊥ ‖ ∠ ⌒ ≌ ∽ √ &#xff08;&#xff09; 【】&#xff5b…

在使用win 7 無線承載網絡時,啟動該服務時,有時會提示:組或資源的狀態不是執行請求操作的正確狀態。 網上有文章指出,解決這個問題的方法是在設備管理器中啟動“Microsoft托管網絡虛擬適配

在使用win 7 無線承載網絡時&#xff0c;啟動該服務時&#xff0c;有時會提示&#xff1a;組或資源的狀態不是執行請求操作的正確狀態。 網上有文章指出&#xff0c;解決這個問題的方法是在設備管理器中啟動“Microsoft托管網絡虛擬適配器”&#xff0c;見 http://jingyan.baid…

阿里一年,聊聊我成長了什么,入職阿里的職業生涯感悟

2018.5.31~2019.5.31&#xff0c;一段精彩的旅程&#xff0c;渡過了在阿里一年的時光&#xff0c;這段時光有快樂、有焦慮、有迷茫、更有思考&#xff0c;思考的是自己過去的種種不足、思考的是一些現在看來之前錯誤的想法、思考的是如何成為一個更好的技術人&#xff0c;將這一…

偏差-方差分解(轉)

1、定義 這里所說的偏差-方差分解就是一種解釋模型泛化性能的一種工具。它是對模型的期望泛化錯誤率進行拆解。 樣本可能出現噪聲&#xff0c;使得收集到的數據樣本中的有的類別與實際真實類別不相符。對測試樣本 x&#xff0c;另 yd 為 x 在數據集中的標記&#xff0c;y 為真實…

用過C#的朋友可能認為它是一種十分安全的語言,其實C#也可以做到經典的緩沖區溢出。 本文章將用一個實例來描述C#究竟是如何發生緩沖區溢出的! 首先建立一個C# Console工程,并開啟工程的“允許

用過C#的朋友可能認為它是一種十分安全的語言&#xff0c;其實C#也可以做到經典的緩沖區溢出。 本文章將用一個實例來描述C#究竟是如何發生緩沖區溢出的&#xff01; 首先建立一個C# Console工程&#xff0c;并開啟工程的“允許不安全代碼”選項 鍵入代碼&#xff1a; [csharp]…

COOKIE偽造登錄網站后臺

1.關于XSS&#xff08;跨站腳本攻擊&#xff09;和CSRF&#xff08;跨站請求偽造&#xff09;的知識&#xff0c;xss表示Cross Site Scripting(跨站腳本攻擊)&#xff0c;它與SQL注入攻擊類似&#xff0c;SQL注入攻擊中以SQL語句作為用戶輸入&#xff0c;從而達到查詢/修改/刪除…

Spring Cloud 學習 (五) Zuul

Zuul 作為路由網關組件&#xff0c;在微服務架構中有著非常重要的作用&#xff0c;主要體現在以下 6 個方面&#xff1a; Zuul, Ribbon 以及 Eureka 相結合&#xff0c;可以實現智能路由和負載均衡的功能&#xff0c;Zuul 能夠將請求流量按某種策略分發到集群狀態的多個服務實例…

如何利用445端口進行入侵滲透 445端口入侵原因詳細解析。大家在進行入侵滲透個人電腦的時候,經常會碰到各種各樣的端口,比如135,1433,445,3306等端口,現在小編就給大家講解下445端口如

如何利用445端口進行入侵滲透 445端口入侵原因詳細解析。大家在進行入侵滲透個人電腦的時候&#xff0c;經常會碰到各種各樣的端口&#xff0c;比如135&#xff0c;1433&#xff0c;445&#xff0c;3306等端口&#xff0c;現在小編就給大家講解下445端口如何入侵。 445端口入侵…

項目復盤

前言 最近一年半多一直在做一個CMS項目&#xff0c;做了快兩年了也沒有上線&#xff0c;而且開發還走了不少&#xff0c;其中有不少原因是因為開發中頻繁改動需求導致開發人員失去耐心&#xff0c;但是其中還有一個重要的原因就是架構設計的不好&#xff0c;導致很多服務的邊界…

父、子頁面之間頁面元素的獲取,方法的調用

一、在iframe頁面上調取父級頁面元素 1.在父頁面上獲取iframe頁面元素(在父頁面修改子頁面div的背景色為紅色) js代碼如下&#xff1a; 1 <script type"text/javascript"> 2 window.onload function(){ 3 var iframe document.getElementById(iframeId)…

fiddler,他和其他抓包軟件有什么區別,如何使用fiddler進行抓包

前言&#xff1a;本文章是搭配《批量獲取微信公眾號》一文&#xff0c;介于群里朋友很熱情&#xff0c;我就趁著上班測完bug 來撰寫該文章&#xff0c;那么讀完本文&#xff0c;你會學習到什么呢&#xff1f; 什么是fiddler&#xff0c;他和其他抓包軟件有什么區別&#xff0c…

Vue導入非模塊化的第三方插件功能無效解決方案

一、問題&#xff1a; 最近在寫vue項目時&#xff0c;想引入某些非模塊化的第三方插件時&#xff0c;總是發現會有報錯。且在與本地運行插件測試對比時發現插件根本沒有注入到jQuery中&#xff08;console.log($.fn)查看當前jq有哪些方法&#xff09;&#xff0c;例如&#xff…

ES6筆記 -- 字符串拓展

字符串拓展 Unicode 相關 JS 允許使用/uxxxx的Unicode方式顯示字符, 但是只限于碼點在/u0000~/uFFFF之間, 超過該范圍的碼點必須用雙字節形式表示ES6 中, 將碼點放入大括號內, 就可以解讀JS 不能處理4個字節的字符, 字符串長度會被誤判為2ES6 提供了codePointAt方法, 能夠正確處…

android 轉發短信

通過這些代碼也可以對遠程手機實現短信控制。有興趣的可以自己改一下&#xff0c;說一下簡單的原理&#xff0c;要實現控制的話&#xff0c;必須得走一個固定的號碼&#xff0c;固定的格式&#xff0c;然后通過得到此號碼的內容&#xff0c;然后通過固定的內容&#xff0c;就可…

[Noi2016]區間

傳送門 Code /* 線段樹 尺取法 */ #include<bits/stdc.h> #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)>(b)?(b):(a)) #define reg register inline int read() {int x0,f1;char chgetchar();while(ch<0||ch>9){if(…

安裝CentOS6.8并配置網絡圖文解說親測全過程

安裝環境&#xff1a; 本文是在win10系統安裝上VMWare并配置Centos6.8虛擬機。 準備工作 1.安裝VMWare虛擬機 1.1下載VMWare12資源鏈接&#xff1a;https://pan.baidu.com/s/1AhfMSDXLO-aA0eMqnuMWHg 提取碼&#xff1a;iftd 1.2安裝VMWare&#xff0c;在安裝過程中需要輸入密鑰…

Paxos算法是萊斯利·蘭伯特(Leslie Lamport)1990年提出的一種基于消息傳遞的一致性算法。

Paxos算法是萊斯利蘭伯特(Leslie Lamport)1990年提出的一種基于消息傳遞的一致性算法。Paxos算法解決的問題是一個分布式系統如何就某個值&#xff08;決議&#xff09;達成一致。在工程實踐意義上來說&#xff0c;就是可以通過Paxos實現多副本一致性&#xff0c;分布式鎖&…

09、策略模式

2019獨角獸企業重金招聘Python工程師標準>>> 策略模式與工廠模式最大的區別在于&#xff0c;策略模式注重的是對算法的維護&#xff0c;也可以理解為對算法的封裝。而工廠模式&#xff0c;則只是負責創建類&#xff0c;在剛接觸策略模式時候&#xff0c;往往與工廠模…

Linux創建、刪除文件和文件夾命令

https://www.cnblogs.com/c-x-m/p/9794082.html轉載于:https://www.cnblogs.com/sun-ldy/p/10279025.html