您好,登錄后才能下訂單哦!
授權(quán)的方式包括web授權(quán)和方法授權(quán),web授權(quán)是通過(guò)url攔截進(jìn)行授權(quán),方法授權(quán)是通過(guò)方法攔截進(jìn)行授權(quán),他們都會(huì)調(diào)用accessDecisionManager進(jìn)行授權(quán)決策,若為web授權(quán)則攔截器為:FilterSecurityIntecepter,若為方法授權(quán)則攔截器為:MethodSecurityIntecepter,如果同時(shí)通過(guò)web授權(quán)和方法授權(quán)則先進(jìn)行web授權(quán)再執(zhí)行方法授權(quán),最后決策通過(guò),則允許訪問(wèn)資源,否則將禁止訪問(wèn)。
1.?????? 準(zhǔn)備環(huán)境
在user_dbs數(shù)據(jù)庫(kù)中創(chuàng)建表:
角色表:
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);
?
?
?
權(quán)限表:
CREATE TABLE `t_permission` (
`id` VARCHAR(32) NOT NULL,
`code` VARCHAR(32) NOT NULL COMMENT '權(quán)限標(biāo)識(shí)符',
`description` VARCHAR(64) DEFAULT NULL COMMENT '描述',
`url` VARCHAR(128) DEFAULT NULL COMMENT '請(qǐng)求地址',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
?
INSERT INTO `t_permission`(`id`,`code`,`description`,`url`) VALUES ('1','p1','測(cè)試資源
1','/r/r1'),('2','p3','測(cè)試資源2','/r/r2');
?
角色權(quán)限關(guān)系表:
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èn)證攔截,并對(duì)/r/**下的資源進(jìn)行簡(jiǎn)單的保護(hù),我們還可以通過(guò)給http.authorizeRequests()添加多個(gè)節(jié)點(diǎn)來(lái)進(jìn)行靈活的授權(quán)控制
.authorizeRequests()?() ?.antMatchers().hasAuthority()?() ?.antMatchers().hasAuthority()?() ?.antMatchers().access()?() ?.antMatchers().authenticated()?() ?.anyRequest().permitAll()?() ?.and() ?.formLogin()
?
(1)http.authorizeRequests() 方法有多個(gè)子節(jié)點(diǎn),每個(gè)macher按照他們的聲明順序執(zhí)行
(2)指定”/r/r1”url擁有p1權(quán)限能夠訪問(wèn)
(5)指定除了r1,r2,r3之外”/r/**”資源通過(guò)身份認(rèn)證就可以訪問(wèn)
(6)其它的資源不做保護(hù),可以任意訪問(wèn)
?
注意:規(guī)則的順序,更具體的規(guī)則應(yīng)該先寫(xiě)
例如:
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/admin/login").permitAll()
第一條規(guī)則中已經(jīng)規(guī)定以/admin開(kāi)始的url需要具備ADMIN的角色才能訪問(wèn),即使第二條規(guī)則中/admin/login這個(gè)url可以被訪問(wèn)在訪問(wèn)/admin/login時(shí)也需要具備ADMIN的角色,因?yàn)樗谇懊?,第二條規(guī)則被忽略。
因此登錄頁(yè)面的規(guī)則應(yīng)該放在前面
.antMatchers("/admin/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
保護(hù)URL常用的方法有:
Authenticated()保護(hù)URL,需要用戶登錄
PermitAll()指定URL無(wú)需保護(hù),一般用于靜態(tài)資源文件
hasRole(String role)限制單個(gè)角色訪問(wèn),角色將被增加”ROLE_”,所以”ADMIN”將和”ROLE_ADMIN”比較
hasAuthority(String authority)限制單個(gè)權(quán)限訪問(wèn)
hasAnyRole(String Roles…)允許多個(gè)角色訪問(wèn)
hasAnyyAuthority(String …Authorities)允許多個(gè)權(quán)限訪問(wèn)
access(String attribute)可以創(chuàng)建復(fù)雜的限制
hasIpAddress(String ipAddressExpression)限制ip地址或子網(wǎng)
?
?
方法授權(quán):
從Spring Security2.0版開(kāi)始支持服務(wù)層方法授權(quán)。
我們可以在任何@Configuration實(shí)例上使用@EnableGlobalMethodSecurity來(lái)啟用基于注解的安全性,以下將啟用Spring Security的 @Secured 注釋
@Configuration ?@EnableGlobalMethodSecurity(securedEnabled?=?) ?WebSecurityConfig?WebSecurityConfigurerAdapter?{
…
}
然后向方法(類或接口)添加注解就會(huì)限制對(duì)該方法的訪問(wèn)。
例如:
BankService?{ ?????@Secured() ?????Account?readAccount(Long?id); ?????@Secured() ?????Account[]?findAccounts(); ?????@Secured() ?????Account?post(Account?account,?amount); ?}
以上配置表明readAccount和findAccounts方法可以匿名訪問(wèn)
Post方法需要有TELLER角色才能訪問(wèn)
?
啟用prePost注解
@Configuration ?@EnableGlobalMethodSecurity(prePostEnabled?=?) ?WebSecurityConfig?WebSecurityConfigurerAdapter?{
…
}
例如:
BankService?{ ?????@PreAuthorize() ?????Account?readAccount(Long?id); ?????@PreAuthorize() ?????Account[]?findAccounts(); ?????@PreAuthorize() ?????Account?post(Account?account,?amount); ?}
以上配置表明readAccount和findAccounts可以匿名訪問(wèn)
Post方法需要同時(shí)擁有p_transfer和p_read_account權(quán)限才能訪問(wèn)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。