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

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


Paste_Image.png

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

  1. 需要將用戶劃分為不同的組,而組之間的權(quán)限是重疊的。
  2. 需要全局地、批量的修改一類用戶的權(quán)限。
  3. 當擁有大量用戶時,避免直接面向用戶級別授權(quán)。

加入“分組”的方式一定程度增加了用戶權(quán)限管理的復(fù)雜,但其帶來的低耦合、易維護的價值已遠超過復(fù)雜性。這種將用戶權(quán)限集中到組的技術(shù)通常稱為基于組的用戶訪問控制,即Group Based Access Control,GBAC(屬于RBAC的一種)。下面就為大家講解一下Spring Security是如何實現(xiàn)GBAC的。
1.根據(jù)上圖,生成MySql數(shù)據(jù)庫腳本和測試數(shù)據(jù)
數(shù)據(jù)庫中,Authorities表中的數(shù)據(jù)已經(jīng)清空,我們之前建立的用戶和權(quán)限的對應(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)限的功能。同時將Spring Security默認創(chuàng)建的UserDetailsService發(fā)布為Spring的bean,這樣我們就可一直獲取該方法,完成一些基本的用戶管理功能,比如創(chuàng)建、刪除用戶,加入分組等。

    /**
     * Description:配置認證細節(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);
    }

    /**
     * 獲取默認創(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("---------------------------");
    }
}

啟動服務(wù)器,驗證用戶認證。
這樣我們非常簡單的實現(xiàn)了基于GBAC的認證功能

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容