ch08:配置GBAC(基于組的訪問控制),提高用戶與權(quán)限靈活性

通常系統(tǒng)會(huì)擁有大量的用戶怖竭,同時(shí)系統(tǒng)也會(huì)劃分非常多的權(quán)限恰力,為了能夠更方便的管理用戶和權(quán)限叉谜,往往需要隔離用戶和權(quán)限,使它們不直接建立聯(lián)系踩萎,而是通過“分組”停局,即將這些權(quán)限通過一定的邏輯劃分為若干組,每個(gè)組包含若干權(quán)限,每個(gè)用戶有屬于若干組董栽,如圖所示码倦。


Paste_Image.png

這種將權(quán)限進(jìn)行打包處理的方式可以適應(yīng)一下場景:

  1. 需要將用戶劃分為不同的組,而組之間的權(quán)限是重疊的锭碳。
  2. 需要全局地袁稽、批量的修改一類用戶的權(quán)限。
  3. 當(dāng)擁有大量用戶時(shí)擒抛,避免直接面向用戶級(jí)別授權(quán)推汽。

加入“分組”的方式一定程度增加了用戶權(quán)限管理的復(fù)雜,但其帶來的低耦合歧沪、易維護(hù)的價(jià)值已遠(yuǎn)超過復(fù)雜性歹撒。這種將用戶權(quán)限集中到組的技術(shù)通常稱為基于組的用戶訪問控制,即Group Based Access Control槽畔,GBAC(屬于RBAC的一種)栈妆。下面就為大家講解一下Spring Security是如何實(shí)現(xiàn)GBAC的胁编。
1.根據(jù)上圖厢钧,生成MySql數(shù)據(jù)庫腳本和測試數(shù)據(jù)
數(shù)據(jù)庫中,Authorities表中的數(shù)據(jù)已經(jīng)清空嬉橙,我們之前建立的用戶和權(quán)限的對(duì)應(yīng)關(guān)系已經(jīng)不存在早直。

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for authorities
-- ----------------------------
DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities` (
  `username` varchar(50) NOT NULL,
  `authority` varchar(50) NOT NULL,
  UNIQUE KEY `ix_auth_username` (`username`,`authority`),
  CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of authorities
-- ----------------------------

-- ----------------------------
-- Table structure for groups
-- ----------------------------
DROP TABLE IF EXISTS `groups`;
CREATE TABLE `groups` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `group_name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of groups
-- ----------------------------
INSERT INTO `groups` VALUES ('1', 'Users');
INSERT INTO `groups` VALUES ('2', 'Administrators');

-- ----------------------------
-- Table structure for group_authorities
-- ----------------------------
DROP TABLE IF EXISTS `group_authorities`;
CREATE TABLE `group_authorities` (
  `group_id` bigint(20) NOT NULL,
  `authority` varchar(50) NOT NULL,
  KEY `fk_group_authorities_group` (`group_id`),
  CONSTRAINT `fk_group_authorities_group` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of group_authorities
-- ----------------------------
INSERT INTO `group_authorities` VALUES ('1', 'ROLE_USER');
INSERT INTO `group_authorities` VALUES ('2', 'ROLE_USER');
INSERT INTO `group_authorities` VALUES ('2', 'ROLE_ADMIN');

-- ----------------------------
-- Table structure for group_members
-- ----------------------------
DROP TABLE IF EXISTS `group_members`;
CREATE TABLE `group_members` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `group_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_group_members_group` (`group_id`),
  CONSTRAINT `fk_group_members_group` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of group_members
-- ----------------------------
INSERT INTO `group_members` VALUES ('1', 'user', '1');
INSERT INTO `group_members` VALUES ('2', 'admin', '2');

-- ----------------------------
-- Table structure for persistent_logins
-- ----------------------------
DROP TABLE IF EXISTS `persistent_logins`;
CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of persistent_logins
-- ----------------------------

-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `username` varchar(50) NOT NULL,
  `password` varchar(500) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of users
-- ----------------------------
INSERT INTO `users` VALUES ('admin', '$2a$10$tpJFaP1dBCLWGpPsreD8zOE2HxOJzuZ3cRHmhOODYSZLUrmlFkySi', '1');
INSERT INTO `users` VALUES ('user', '$2a$10$tpJFaP1dBCLWGpPsreD8zOE2HxOJzuZ3cRHmhOODYSZLUrmlFkySi', '1');
SET FOREIGN_KEY_CHECKS=1;

修改WebSecurityConfigurerAdapter開啟Spring Security分組功能,并關(guān)閉用戶直接獲取權(quán)限的功能市框。同時(shí)將Spring Security默認(rèn)創(chuàng)建的UserDetailsService發(fā)布為Spring的bean霞扬,這樣我們就可一直獲取該方法,完成一些基本的用戶管理功能枫振,比如創(chuàng)建喻圃、刪除用戶,加入分組等粪滤。

    /**
     * Description:配置認(rèn)證細(xì)節(jié)
     *
     * @param auth
     * @return
     * @Author: 瓦力
     * @Date: 2017/7/21 17:04
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .jdbcAuthentication()
                .passwordEncoder(passwordEncoder())//啟用密碼加密功能
                .dataSource(dataSource);
    }

    /**
     * 獲取默認(rèn)創(chuàng)建的UserDetailsService斧拍,開啟分組功能,關(guān)閉用戶直接授權(quán)功能杖小,并發(fā)布為Spring Bean
     *
     * @param auth
     * @return
     */
    @Bean
    @Autowired
    public UserDetailsService userDetailsService(AuthenticationManagerBuilder auth) {
        UserDetailsService userDetailsService = auth.getDefaultUserDetailsService();
        if (JdbcUserDetailsManager.class.isInstance(userDetailsService)) {
            JdbcUserDetailsManager jdbcUserDetailsManager = (JdbcUserDetailsManager) userDetailsService;
            jdbcUserDetailsManager.setEnableGroups(true);//開啟分組功能
            jdbcUserDetailsManager.setEnableAuthorities(false);//關(guān)閉用戶直接獲取權(quán)限功能
        }
        return userDetailsService;
    }

利用UserDetailsService建立用戶管理服務(wù)

@Component
public class UserService {
    @Autowired
    UserDetailsService userDetailsService;

    @PostConstruct
    public void init() {
        System.out.println("---------------------------");
        System.out.println(userDetailsService.getClass());
        System.out.println("---------------------------");
    }
}

啟動(dòng)服務(wù)器肆汹,驗(yàn)證用戶認(rèn)證。
這樣我們非常簡單的實(shí)現(xiàn)了基于GBAC的認(rèn)證功能

代碼示例:https://github.com/wexgundam/spring.security/tree/master/ch08

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末予权,一起剝皮案震驚了整個(gè)濱河市昂勉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扫腺,老刑警劉巖岗照,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡攒至,警方通過查閱死者的電腦和手機(jī)煞肾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗓袱,“玉大人籍救,你說我怎么就攤上這事∏ǎ” “怎么了蝙昙?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梧却。 經(jīng)常有香客問我奇颠,道長,這世上最難降的妖魔是什么放航? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任烈拒,我火速辦了婚禮,結(jié)果婚禮上广鳍,老公的妹妹穿的比我還像新娘荆几。我一直安慰自己,他們只是感情好赊时,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布吨铸。 她就那樣靜靜地躺著,像睡著了一般祖秒。 火紅的嫁衣襯著肌膚如雪诞吱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天竭缝,我揣著相機(jī)與錄音房维,去河邊找鬼。 笑死抬纸,一個(gè)胖子當(dāng)著我的面吹牛咙俩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播松却,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼暴浦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了晓锻?” 一聲冷哼從身側(cè)響起歌焦,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎砚哆,沒想到半個(gè)月后独撇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年纷铣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卵史。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搜立,死狀恐怖以躯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情啄踊,我是刑警寧澤忧设,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站颠通,受9級(jí)特大地震影響址晕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顿锰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一谨垃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硼控,春花似錦刘陶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匈织。三九已至浪默,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缀匕,已是汗流浹背纳决。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乡小,地道東北人阔加。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像满钟,于是被迫代替她去往敵國和親胜榔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容