Spring Security(8)

湘王發表於2022-12-01

您好,我是湘王,這是我的部落格園,歡迎您來,歡迎您再來~

 

之前雖然實現了角色和許可權之間的簡單配對,但是如果每一個角色都要重新來過一次,就有點呆板了。如果能夠配置一個「角色模板」,再透過這個模板來配置其他角色,豈不是更簡單?Spring Security雖然沒有角色模板,但可以透過「繼承」的方式來「曲線就國」。

而且有時候角色與使用者並不是完全一一對應的。比如,admin介面只有ROLE_ADMIN角色擁有,manager介面只有ROLE_MANAGER角色擁有。但其實admin是應該擁有manager的許可權的。所以來看看怎麼個「應該」法。

首先,sys_suer表中增加employee使用者:

INSERT INTO sys_user VALUES (3, 'employee', '123456', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

 

然後在sys_role表中增加ROLE_EMPLOYEE角色:

INSERT INTO sys_role VALUES (3, 'ROLE_EMPLOYEE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

 

再在sys_permission許可權表中增加角色許可權:

INSERT INTO sys_permission VALUES (5,3,'/employee','read',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

INSERT INTO sys_permission VALUES (6,3,'/employee','remove',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

 

 

修改LoginController,增加employee介面:

@GetMapping("/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String admin() {
    return "admin有ROLE_ADMIN角色";
}

@GetMapping("/manager")
@PreAuthorize("hasRole('ROLE_MANAGER')")
public String manager() {
    return "manager有ROLE_MANAGER角色";
}

@GetMapping("/employee")
@PreAuthorize("hasRole('ROLE_EMPLOYEE')")
public String employee() {
    return "employee有ROLE_EMPLOYEE角色";
}

 

 

然後在WebSecurityConfiguration中引入Spring Security的RoleHierarchy角色繼承類:

// 角色繼承
@Bean
public RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    // 多個角色用【>】表示,【>】左邊角色的許可權要大於右邊角色的許可權
    String hierarchy = "ROLE_ADMIN > ROLE_MANAGER " + System.lineSeparator() +
            " ROLE_MANAGER > ROLE_EMPLOYEE";
    // 也可以寫成  "ROLE_ADMIN > ROLE_MANAGER > ROLE_EMPLOYEE";
    roleHierarchy.setHierarchy(hierarchy);
    return roleHierarchy;
}

 

 

透過Postman測試使用者各自擁有的角色:

1、admin { ROLE_ADMIN, ROLE_MANAGER, ROLE_EMPLOYEE }

2、manager { ROLE_MANAGER, ROLE_EMPLOYEE }

3、employee { ROLE_EMPLOYEE }

可以看出來,Spring Security有幾個特點:

1、角色可以被繼承,但許可權並不能“跟隨”角色一起被繼承

2、admin只能訪問/admin/create和/admin/read這兩個介面

3、manager也只能訪問/manager/create和/manager/remove這兩個介面

4、admin雖然繼承了user的角色ROLE_MANAGER,但並沒有顯示地獲得ROLE_MANAGER對應的許可權,因為加入許可權後,角色繼承就會失效

 

 

 

因為許可權無法跟隨角色被繼承,所以需要手動去完善許可權。為了讓admin也能訪問manager的介面,要賦予角色更多的許可權。現在把manager和employee的許可權都賦予admin:

INSERT INTO sys_permission VALUES (7,1,'/manager','create',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

INSERT INTO sys_permission VALUES (8,1,'/manager','remove',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

INSERT INTO sys_permission VALUES (9,1,'/employee','read',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

INSERT INTO sys_permission VALUES (10,1,'/employee','remove',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);

 

然後在LoginController裡再增加employee的許可權:

@GetMapping("/employee/read")
@PreAuthorize("hasPermission('/employee', 'read')")
public String employeeRead() {
    return "employee有ROLE_EMPLOYEE角色的read許可權";
}

@GetMapping("/employee/remove")
@PreAuthorize("hasPermission('/employee', 'remove')")
public String employeeRemove() {
    return "employee有ROLE_EMPLOYEE角色的remove許可權";
}

 

 

透過admin登入,分別訪問如下介面:

 

 

 

可以看到,admin已經有之前manager和employee的許可權了。

Spring Security雖然比較簡單,也很方便,多適用於一些比較小型的應用系統,角色簡單,許可權不多。如果要實現一些比較複雜的許可權功能,Spring Security就會有點力不從心了,而且會出現諸如自定義filter被執行多次的問題。所以,一般在大型或企業級應用中,都不會,至少不會完全依賴Spring Security,而是依據實際業務需求,實現自定義的許可權系統。

 

 


 

 

感謝您的大駕光臨!諮詢技術、產品、運營和管理相關問題,請關注後留言。歡迎騷擾,不勝榮幸~

 

相關文章