Spring Security七:授權

授權的方式包括web授權和方法授權,web授權是通過url攔截進行授權,方法授權是通過方法攔截進行授權,他們都會調用accessDecisionManager進行授權決策,若爲web授權則攔截器爲:FilterSecurityIntecepter,若爲方法授權則攔截器爲:MethodSecurityIntecepter,如果同時通過web授權和方法授權則先進行web授權再執行方法授權,最後決策通過,則允許訪問資源,否則將禁止訪問。

1.       準備環境

user_dbs數據庫中創建表:

角色表:

CREATE TABLE t_role (

id VARCHAR(32) NOT NULL,

role_name VARCHAR(255) DEFAULT NULL,

description VARCHAR(255) DEFAULT NULL,

create_time DATETIME DEFAULT NULL,

update_time DATETIME DEFAULT NULL,

STATUS CHAR(1) NOT NULL,

PRIMARY KEY (id),

UNIQUE KEY unique_role_name (role_name)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO t_role(id,role_name,description,create_time,update_time,STATUS) VALUES ('1','管理員',NULL,NULL,NULL,'');

 

用戶角色表:

CREATE TABLE `t_user_role` (

`user_id` VARCHAR(32) NOT NULL,

`role_id` VARCHAR(32) NOT NULL,

`create_time` DATETIME DEFAULT NULL,

`creator` VARCHAR(255) DEFAULT NULL,

PRIMARY KEY (`user_id`,`role_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_user_role`(`user_id`,`role_id`,`create_time`,`creator`) VALUES

('1','1',NULL,NULL);

 

 

 

權限表:

CREATE TABLE `t_permission` (

`id` VARCHAR(32) NOT NULL,

`code` VARCHAR(32) NOT NULL COMMENT '權限標識符',

`description` VARCHAR(64) DEFAULT NULL COMMENT '描述',

`url` VARCHAR(128) DEFAULT NULL COMMENT '請求地址',

PRIMARY KEY (`id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_permission`(`id`,`code`,`description`,`url`) VALUES ('1','p1','測試資源

1','/r/r1'),('2','p3','測試資源2','/r/r2');

 

角色權限關係表:

CREATE TABLE `t_role_permission` (

`role_id` VARCHAR(32) NOT NULL,

`permission_id` VARCHAR(32) NOT NULL,

PRIMARY KEY (`role_id`,`permission_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_role_permission`(`role_id`,`permission_id`) VALUES ('1','1'),('1','2');

 

2.       修改UserDetailService

(1)    修改dao接口

List<String> findPermissionsByUserId(String userId) {
     String sql = +
             +
             +
             +
             ;
     List<PermissionDto> list = .query(sql, Object[]{userId}, BeanPropertyRowMapper<>(PermissionDto.));
     List<String> permissions = ArrayList<>();
     list.iterator().forEachRemaining(c-> .add(c.getCode()));
     permissions;
 }
 
     (2)修改UserDetailService
          
SpringDataUserDetailsService UserDetailsService {
     UserDao ;
     UserDetails loadUserByUsername(String username) UsernameNotFoundException {
         System..println(+username);
         UserDto user = .getUserByUsername(username);
         (user == ){
             ;
         }
         List<String> permissions = .findPermissionsByUserId(user.getId());
         String[] perarray = String[permissions.size()];
         permissions.toArray(perarray);
         UserDetails userDetails =
                 User.(user.getFullname()).password(user.getPassword()).authorities(perarray).build();
         userDetails;
     }
 }

在前面的例子中我們完成了認證攔截,並對/r/**下的資源進行簡單的保護,我們還可以通過給http.authorizeRequests()添加多個節點來進行靈活的授權控制

.authorizeRequests() ()
 .antMatchers().hasAuthority() ()
 .antMatchers().hasAuthority() ()
 .antMatchers().access() ()
 .antMatchers().authenticated() ()
 .anyRequest().permitAll() ()
 .and()
 .formLogin()

 

1http.authorizeRequests() 方法有多個子節點,每個macher按照他們的聲明順序執行

2)指定”/r/r1”url擁有p1權限能夠訪問

5)指定除了r1,r2,r3之外”/r/**”資源通過身份認證就可以訪問

6)其它的資源不做保護,可以任意訪問

 

注意:規則的順序,更具體的規則應該先寫

例如:

.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/admin/login").permitAll()

第一條規則中已經規定以/admin開始的url需要具備ADMIN的角色才能訪問,即使第二條規則中/admin/login這個url可以被訪問在訪問/admin/login時也需要具備ADMIN的角色,因爲它在前面,第二條規則被忽略。

因此登錄頁面的規則應該放在前面

.antMatchers("/admin/login").permitAll()

.antMatchers("/admin/**").hasRole("ADMIN")
保護URL常用的方法有:

Authenticated()保護URL,需要用戶登錄

PermitAll()指定URL無需保護,一般用於靜態資源文件

hasRole(String role)限制單個角色訪問,角色將被增加”ROLE_”,所以”ADMIN”將和”ROLE_ADMIN”比較

hasAuthority(String authority)限制單個權限訪問

hasAnyRole(String Roles…)允許多個角色訪問

hasAnyyAuthority(String …Authorities)允許多個權限訪問

access(String attribute)可以創建複雜的限制

hasIpAddress(String ipAddressExpression)限制ip地址或子網

 

 

方法授權:

Spring Security2.0版開始支持服務層方法授權。

我們可以在任何@Configuration實例上使用@EnableGlobalMethodSecurity來啓用基於註解的安全性,以下將啓用Spring Security@Secured 註釋

@Configuration
 @EnableGlobalMethodSecurity(securedEnabled = )
 WebSecurityConfig WebSecurityConfigurerAdapter {

}

然後向方法(類或接口)添加註解就會限制對該方法的訪問。

例如:

BankService {
     @Secured()
     Account readAccount(Long id);
     @Secured()
     Account[] findAccounts();
     @Secured()
     Account post(Account account, amount);
 }
以上配置表明readAccount和findAccounts方法可以匿名訪問
Post方法需要有TELLER角色才能訪問
 
啓用prePost註解
@Configuration
 @EnableGlobalMethodSecurity(prePostEnabled = )
 WebSecurityConfig WebSecurityConfigurerAdapter {

}

例如:
BankService {
     @PreAuthorize()
     Account readAccount(Long id);
     @PreAuthorize()
     Account[] findAccounts();
     @PreAuthorize()
     Account post(Account account, amount);
 }
以上配置表明readAccount和findAccounts可以匿名訪問
Post方法需要同時擁有p_transfer和p_read_account權限才能訪問


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章