您好,登錄后才能下訂單哦!
授權的方式包括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()
(1)http.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權限才能訪問
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。