A. ssm框架訪問控制應該怎麼做
這個就在在人員表了添加一個身份的欄位 user_rank ,用這個來控制。用戶登錄到時候就會用登錄信息,把這個 user_rank 欄位帶出來,在頁面或者鏈接時候加上判斷,哈這是簡單的,看下官方的。
shiro安全框架是目前為止作為登錄注冊最常用的框架,因為它十分的強大簡單,提供了認證、授權、加密和會話管理等功能 。
shiro能做什麼?
認證:驗證用戶的身份
授權:對用戶執行訪問控制:判斷用戶是否被允許做某事
會話管理:在任何環境下使用 Session API,即使沒有 Web 或EJB 容器。
加密:以更簡潔易用的方式使用加密功能,保護或隱藏數據防止被偷窺
Realms:聚集一個或多個用戶安全數據的數據源
單點登錄(SSO)功能。
為沒有關聯到登錄的用戶啟用 "Remember Me「 服務
Shiro 的四大核心部分
Authentication(身份驗證):簡稱為「登錄」,即證明用戶是誰。
Authorization(授權):訪問控制的過程,即決定是否有許可權去訪問受保護的資源。
Session Management(會話管理):管理用戶特定的會話,即使在非 Web 或 EJB 應用程序。
Cryptography(加密):通過使用加密演算法保持數據安全
shiro的三個核心組件:
Subject:正與系統進行交互的人,或某一個第三方服務。所有 Subject 實例都被綁定到(且這是必須的)一個SecurityManager 上。
SecurityManager:Shiro 架構的心臟,用來協調內部各安全組件,管理內部組件實例,並通過它來提供安全管理的各種服務。當 Shiro 與一個 Subject 進行交互時,實質上是幕後的 SecurityManager 處理所有繁重的 Subject 安全操作。
Realms:本質上是一個特定安全的 DAO。當配置 Shiro 時,必須指定至少一個 Realm 用來進行身份驗證和/或授權。Shiro 提供了多種可用此塵渣的 Realms 來獲取安全相關的數據。如關系資料庫(JDBC),INI 及屬性兄段文件等。可以定義自己 Realm 實現來代表自定義的數據源。
shiro整合SSM框架:
1.加入 jar 包:以下jar包自行網路下載
准備好了,接下來要寫Realm方法了,新建shiro包,在包下新建MyRealm.java文件繼承AuthorizingRealm
package shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.crypto.hash.Md5Hash;import org.apache.shiro.crypto.hash.SimpleHash;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import org.springframework.beans.factory.annotation.Autowired;import bean.user;import .user;public class MyRealm extends AuthorizingRealm {
@Autowired private user user;
String pass; /**
* 授權:
*
*/
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Object principal = principalCollection.getPrimaryPrincipal();//獲取登錄的用戶名
if("admin".equals(principal)){ //兩個if根據判斷賦予登錄用戶許可權
info.addRole("admin");
} if("user".equals(principal)){
info.addRole("list");
}
info.addRole("user");
return info;
} /*
* 用戶驗證
*
*/
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//1. token 中獲取登錄的 username! 注意不需要獲取password.
Object principal = token.getPrincipal();
//2. 利用 username 查詢資料庫得到用戶的信息.
user user=user.findbyname((String) principal); if(user!=null){
pass=user.getPass();
}
String credentials = pass; //3.設置鹽值 ,(加密的調料,讓加密出來的東西更具安全性,一般是通過資料庫查詢出來的。 簡單的說,就是把密碼根據特定的東西而進行動態加密,如果別人不知道你的鹽值,就解不出你的密碼)
String source = "abcdefg";
ByteSource credentialsSalt = new Md5Hash(source);
//當前 Realm 的name
String realmName = getName(); //返回值實例化
SimpleAuthenticationInfo info =
new SimpleAuthenticationInfo(principal, credentials,
credentialsSalt, realmName);
return info;
} //init-method 配置.
public void setCredentialMatcher(){
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");//MD5演算法加密
credentialsMatcher.setHashIterations(1024);//1024次循環加密
setCredentialsMatcher(credentialsMatcher);
}
//用來測試的算出密碼password鹽值加密後的結果,下面方法用於新增用戶添加到資料庫操作的,我這里就直接用main獲得,直接資料庫添加了,省時間
public static void main(String[] args) {
String saltSource = "abcdef";
String hashAlgorithmName = "MD5";
String credentials = "passwor";
Object salt = new Md5Hash(saltSource); int hashIterations = 1024;
Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
System.out.println(result);
}
}
好了,接下來我們寫一個簡單的action來通過shiro登錄驗證。
//登錄認證
@RequestMapping("/shiro-login") public String login(@RequestParam("username") String username,
@RequestParam("password") String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try { //執行認證操作. subject.login(token);
}catch (AuthenticationException ae) {
System.out.println("登陸失敗: " + ae.getMessage()); return "/index";
}
return "/shiro-success";
}
//溫馨提示:記得在注冊中密碼存入資料庫前也記得加密哦,提供一個utils方法//進行shiro加密,返回加密後的結果public static String md5(String pass){
String saltSource = "blog";
String hashAlgorithmName = "MD5";
Object salt = new Md5Hash(saltSource);int hashIterations = 1024;
Object result = new SimpleHash(hashAlgorithmName, pass, salt, hashIterations);
String password = result.toString();return password;
}
好了,shiro登錄驗證到這里完了
B. Shiro中的filter
DefaultFilter
shiro中提供的默認filter
FilterChainManager
通過配置創建對應的filterChain
Shiro通過此配置可初始化FilterChainManager中的filterChain,結構為 url ->filter列表
SpringShiroFilter
入口filter,攔截所有請求,通過請求的url匹配到對應的filterChain,然後通過Chain對請求進行,認證或者授權的處理
OncePerRequestFilter
OncePerRequestFilter 用於防止多次執行 Filter;也就是說一次請求只會走一次攔截器鏈;
另外提供 enabled 屬性,表示是否開啟該攔截器實例
實現了 doFilter 方法,提供了抽象方法 doFilterInternal 。
在doFilter中驗證當前的Filter有沒有執行過,如果已經執行過一次或者當前filter被禁用,則直接執行下一個Filter。如果沒有執行過則執行 doFilterInternal 方法
AbstractShiroFilter
創建Subject,綁定subject到當前線程,根據url獲取filterChain並執行filterChain
通過請求的url來匹配FilterChainManager中的FilterChain,這個方法會返回一個 ProxiedFilterChain
ProxiedFilterChain
存儲了tomcat的Filter 和shiro內部的filter
shiro內部的過濾器執行完後會切換到tomcat的過濾器繼續執行
默認filter
除了LogoutFilter,其他都繼承了AdviceFilter
AdviceFilter
AdviceFilter 提供了 AOP 風格的支持,類似於 SpringMVC 中的 Interceptor:
許可權驗證在preHandle中實現
PathMatchingFilter
PathMatchingFilter 提供了基於 Ant 風格的請求路徑匹配功能及攔截器參數解析的功能,如
「 /admin roles[admin,user] 」自動根據 「,」 分割,解析成 /admin -> [admin,user] 存入 appliedPaths 中
實現了 preHandle 方法,通過請求的url匹配url對應的許可權,解析許可權串 調用子類的 onPreHandle 對許可權進行處理
AnonymousFilter
提供匿名訪問功能,實現了 onPreHandle 直接返回true,所以配置 anon 的url任何人都可以訪問
AccessControlFilter
提供了資源訪問控制的基礎功能
實現了 onPreHandle ,這里拆分出了
isAccessAllowed (是否允許訪問)和 onAccessDenied (訪問被拒絕時)這兩個方法供子類實現
AuthenticationFilter
實現了 isAccessAllowed 方法,驗證用戶是否已經登錄,沒有登錄將被拒絕
FormAuthenticationFilter
繼承自 AuthenticationFilter 只有用戶登錄過後才能通過
實現了 onAccessDenied 方法,如果請求的地址是登錄地址,這里會嘗試自動登錄,否則跳轉到登錄頁面
BasicHttpAuthenticationFilter
提供了基於 HttpBasic認證的方式
AuthorizationFilter
實現了 onAccessDenied 方法,如果沒有認證通過,則跳轉到登錄或者認證失敗的頁面
對用戶所訪問資源的許可權進行認證
HttpMethodPermissionFilter
將HTTP請求的方法(例如GET、POST等)轉換為相應的動作並構造一個相應的許可權
如get 被轉換為 read,put 轉換為 update,post轉換為create等
許可權配置:/users perms[users]
請求: get /users
將會驗證 用戶是否擁有users:read許可權
RolesAuthorizationFilter
驗證用戶是否用對對應的角色
UserFilter
實現了 isAccessAllowed 和 onAccessDenied 方法,驗證用戶是否登錄過,如果驗證未通過則跳轉到登錄頁面
C. postman嫻嬭瘯鐧誨綍shiro
springboot欏圭洰浣跨敤浜嗚掕壊鏉冮檺shiro綆$悊錛屾垜瑕佹祴璇曞叾瀹冪殑鎺ュ彛浣嗘槸闇瑕佺櫥褰曟垚鍔熷悗鎵嶈兘嫻嬭瘯錛岃В鍐寵繖涓闂棰樻湁涓ょ嶆柟娉曘
1.postman鐩存帴杈撳叆鐢ㄦ埛鍚嶅拰瀵嗙爜鐧誨綍鎴愬姛鍚庯紝灝卞彲浠ヨ繘琛屽叾瀹冪殑鎺ュ彛嫻嬭瘯銆
2. 浣跨敤swagger鍏堢櫥褰曟垚鍔熷悗錛屽氨鍙浠ユ祴璇曞叾瀹冪殑鎺ュ彛浜嗐
涓錛宲ostman
浜屻乻wagger
springboot闆嗘垚swagger鍚庤塊棶URL
http://localhost:8080/swagger-ui.html
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com..controller")) //鑷宸辯殑鎺у埗鍣ㄥ寘鍚嶈礬寰
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("涓栫晫 API鏂囨。")
.description("涓栫晫 鎿嶄綔鏂囨。")
//鏈嶅姟鏉℃劇綉鍧
.termsOfServiceUrl("http://www..com/")
.version("1.0")
.contact(new Contact("紲栧浗", "http://www..com/", "[email protected]"))
.build();
}
}
pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
D. 銆怱pringBoot銆慡hiro瀹炵幇鏃犵姸鎬佺櫥褰
浣跨敤Shiro瀹炵幇鏈夌姸鎬佺櫥褰曪紝鍗崇敤鎴風櫥褰曠姸鎬佸瓨鍌ㄥ湪鏈嶅姟鍣⊿ession涓錛屼嬌鐢⊿hiro瀹炵幇姣旇緝綆鍗曪紝鎴戣繖閲屾殏涓嶈繘琛岃ㄨ恆
鍦ㄤ竴浜涚幆澧冧腑錛屽彲鑳介渶瑕佹妸 Web 搴旂敤鍋氭垚鏃犵姸鎬佺殑錛屽嵆鏈嶅姟鍣ㄧ鏃犵姸鎬侊紝灝辨槸璇存湇鍔″櫒絝涓嶄細瀛樺偍鍍廠ession榪欑嶄笢瑗匡紝鑰屾槸姣忔¤鋒眰鏃跺甫涓妕oken涔嬬被鐨勮繘琛岀敤鎴峰垽鏂銆
浣跨敤Shiro瀹炵幇鏃犵姸鎬佺櫥褰曠殑涓昏佹ラゆ湁錛岀佺敤緙撳瓨銆佽劇疆涓嶅壋寤簊ession銆佸叧闂璖ession楠岃瘉銆佸叧闂璖ession瀛樺偍銆佹敞鍏ヨ嚜瀹氫箟鎷︽埅鍣ㄣ佸紑鍚瘲hiro鐨勬敞瑙(濡侤RequiresRoles,@RequiresPermissions)絳夈
鑾峰彇token,榪欓噷token鍐欐諱負admin
娣誨姞澧炲垹鏀規煡鎺ュ彛錛屽苟璁劇疆闇瑕佺殑璁塊棶鏉冮檺
鍏抽敭鏄璁劇疆涓嶅壋寤篠ession
涓昏佸姛鑳藉氨鏄鎷︽埅http璇鋒眰錛岃繘琛岃よ瘉鎺堟潈錛屾敞鎰忎笉瑕佹嫤鎴鐧誨綍璇鋒眰
鍦⊿tatelessAuthcFilter鎷︽埅鍣ㄤ腑錛屼細璋冪敤StatelessRealm榪涜宼oken璁よ瘉鍙婄敤鎴鋒巿鏉冦
鎴戣繖閲岃劇疆token涓篴dmin鏃舵嫢鏈夊炲垹鏀規煡鐨勬潈闄愩
token涓簎ser鏃訛紝鍙鎷ユ湁鏌ョ殑鏉冮檺銆
鍏朵粬token錛屾棤浠諱綍鏉冮檺銆
涓昏佹槸紱佺敤緙撳瓨銆佷笉鍒涘緩Session銆佸叧闂璖ession楠岃瘉銆佸叧闂璖ession瀛樺偍銆佹敞鍏ラ厤緗鎷︽埅鍣ㄣ佸紑鍚鏉冮檺鏍¢獙娉ㄨВ絳夈