Spring Security系列二 用戶登錄認證數據庫實現

前言

在前面Spring Security系列一 權限控制基本功能實現中,我們已經實現了基本功能,這一章我們來把用戶的登錄認證修改成貼近實際的數據庫獲取。

Spring Security認證架構

在這之前,先來了解一下Spring Security的認證架構,有篇不錯的分析文章,具體可以看這裏:https://my.oschina.net/u/865921/blog/159849。

總的來說,Spring Security通過filter來控制web應用的安全,但filter自己不幹事,分別委託給了認證管理器和決策管理器,認證管理器和決策管理器再分別委託給Provider和Voter,就這樣一級級委託下來,委託的最底層就是需要我們根據實際情況實現的邏輯。可以看下圖:

spring security認證架構

根據我們這次的目標,想用數據庫來儲存用戶的認證數據,那麼我們就需要一個操作數據庫的Provider,這個Spring Security內部已經有了實現,就是DaoAuthenticationProvider,我們只需要實現它委託的UserDetailService即可,這個其實在前面一篇文章中已經有了實現,只不過沒用數據庫而已。對於Voter,選擇內置的RoleVoter就夠用了,它會根據我們的設置來決定是否允許某一個用戶訪問特定的Web資源。

建表

想要把數據存儲在數據庫,第一步當然是建表了,這裏簡單起見,只搞了用戶和權限的基本信息:

CREATE TABLE `USER` (
  `USER_ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `LOGIN_NAME` varchar(32) NOT NULL,
  `PASSWORD` varchar(32) NOT NULL,
  `GMT_CREATE` datetime NOT NULL,
  PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `USER_AUTH` (
  `USER_AUTH_ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `USER_ID` bigint(20) NOT NULL,
  `AUTH_CODE` varchar(32) NOT NULL,
  `GMT_CREATE` datetime NOT NULL,
  PRIMARY KEY (`USER_AUTH_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into user(login_name,password,gmt_create) values ('admin','123456',now());
insert into user(login_name,password,gmt_create) values ('selfly','123456',now());
insert into user_auth(user_id,auth_code,gmt_create) values (1,'admin',NOW()); -- admin
insert into user_auth(user_id,auth_code,gmt_create) values (2,'user',NOW()) -- user

Spring Security中,貌似用戶都是對應到角色(role)的,但是在實際的應用中一般都是對應到具體的權限碼,這點無須糾結,把它理解爲命名的方式不同而已即可,關於權限碼的授權後面再作細講。

修改CustomUserDetailsService

其實沒多大改動,主要就是把寫死的用戶數據換成從數據庫獲取而已,具體代碼:

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    User user = jdbcDao.querySingleResult(Criteria.select(User.class).where("loginName", new Object[]{s}));
    if (user == null) {
        throw new UsernameNotFoundException("user not found");
    }
    List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();

    List<UserAuth> userAuthList = jdbcDao.queryList(Criteria.select(UserAuth.class).where("userId", new Object[]{user.getUserId()}));
    if (userAuthList != null) {

        for (UserAuth userAuth : userAuthList) {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + userAuth.getAuthCode()));
            LOG.info("loginName:{},authCode:{}", user.getLoginName(), userAuth.getAuthCode());
        }

    }
    return new org.springframework.security.core.userdetails.User(user.getLoginName(), user.getPassword(),
            authorities);
}

測試

修改後,再訪問 http://localhost:8080/login 頁面,分別用adminselfly登錄,權限校驗結果還是跟前面一樣,但後臺的用戶信息已經換成從數據庫獲取了。

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