天天看點

SpringBoot 整合 SpringSecurity 之基于記憶體認證(一)

SpringBoot 整合 SpringSecurity 之基于記憶體認證(一)
SpringBoot 整合 SpringSecurity 之基于記憶體認證(一)

在第一篇的教程中,我們簡單的了解了一下 SpringSecurity 的使用姿勢,添加依賴,在

application.yml

檔案中加幾行配置,就可以實作一個基本的登入認證;

預設的配置隻能設定一個賬号,那麼如果需要多個賬号可以怎麼支援呢?

本文将介紹一下基于記憶體的認證方式

<!-- more -->

I. 記憶體認證

基于記憶體儲存認證資訊的方式,本篇博文中,會介紹兩種常見的使用姿勢

0. 項目配置

環境配置和前面一緻,相關内容可以參考博文: 191223-SpringBoot 整合 SpringSecurity 之起源篇(零)

1. WebSecurityConfigurerAdapter

這裡主要是借助

SpringSecurity

的配置擴充卡來處理,下面是一個簡單的 case

@Configuration
public class SecurityAdapterConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 測試時,可以直接用下面的方式
        //        User.UserBuilder builder = User.withDefaultPasswordEncoder();
        User.UserBuilder builder = User.builder().passwordEncoder(passwordEncoder()::encode);
        auth.inMemoryAuthentication().withUser(builder.username("hui1").password("123456").roles("guest").build());
        auth.inMemoryAuthentication().withUser(builder.username("hui2").password("123456").roles("guest").build());
    }
}           

複制

主要邏輯在

configure

這個方法中,但是需要注意,我們額外的設定了密碼的加密方式, 當我們不設定這個的時候,實際登入的時候會發現,即便你輸入了正确的使用者名密碼,也會提示失敗(歡迎各位大佬實測一下)

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}           

複制

其次,在建立使用者的時候,需要注意的是,除了設定了使用者名和密碼之外,還給使用者加上了一個角色,這個會在後續文章的 RBAC(基于角色的授權)中介紹它的作用

2. UserDetailsService

這裡介紹另外一種方式,在後面的 db 中儲存認證資訊時,也會用到;在 SpringSecurity 的實作中,通過 UserDetailService 這個 bean 來根據使用者名查詢對應的使用者資訊;是以我們隻需要實作一個我們自定義的 Bean 來替換預設的,就可以來實作我們的目标

我們的配置類如下

@Configuration
public class SecurityAutoConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 基于記憶體的認證方式
     *
     * @param passwordEncoder
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        User.UserBuilder users = User.builder().passwordEncoder(passwordEncoder::encode);
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(users.username("1hui").password("123456").roles("guest").build());
        manager.createUser(users.username("2hui").password("666666").roles("manager").build());
        manager.createUser(users.username("3hui").password("root").roles("admin").build());
        return manager;
    }
}           

複制

3. 測試

上面兩種方式,都可以實作在記憶體中儲存認證資訊,接下來我們進入實測環節,首先寫一個 http 接口

@RestController
public class IndexRest {

    public String getUser() {
        // 擷取使用者資訊
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        String userName;
        if (principal instanceof UserDetails) {
            userName = ((UserDetails) principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }

    /**
     * @return
     */
    @GetMapping(path = {"/"})
    public String index() {
        return "hello this is index! welcome " + getUser();
    }
}           

複制

在實際測試時,上面兩種 case 都是 ok 的,下面的示範過程主要是基于第二種方式給出的示例

SpringBoot 整合 SpringSecurity 之基于記憶體認證(一)

II. 其他

0. 系列博文&項目源碼

博文

  • 191223-SpringBoot 整合 SpringSecurity 之起源篇(零)

源碼

  • 工程:https://github.com/liuyueyi/spring-boot-demo
  • 源碼: - https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-security/001-authentication-mem-config - https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-security/001-authentication-mem-userdetail

1. 一灰灰 Blog

盡信書則不如,以上内容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激

下面一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛

  • 一灰灰 Blog 個人部落格 https://blog.hhui.top
  • 一灰灰 Blog-Spring 專題部落格 http://spring.hhui.top