Springboot基於SpringSecurity簡單的登錄驗證


1.1導入依賴

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

1.2配置用戶信息和權限類

SpringSecurity中存在一個UserDetails接口的實現類org.springframework.security.core.userdetails.User,它有三個參數,分別是用戶名、密碼和權限集。我們需要通過自定義 UserDetailsService將用戶和權限信息注入進去。(也可以直接創建寫入,通過自定義UserDetailsService主要是為了從數據庫中讀取用戶信息)。

  • 直接配置
       @Bean
    public UserDetailsService userDetailsService() throws Exception {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
        return manager;
    }
  • 從數據庫中讀取
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private SysUserService userService;

    @Autowired
    private SysRoleService roleService;

    @Autowired
    private SysUserRoleService userRoleService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        // 從數據庫中取出用戶信息
        SysUser user = userService.selectByName(username);

        // 判斷用戶是否存在
        if(user == null) {
            throw new UsernameNotFoundException("用戶名不存在");
        }

        // 添加權限
        List<SysUserRole> userRoles = userRoleService.listByUserId(user.getId());
        for (SysUserRole userRole : userRoles) {
            SysRole role = roleService.selectById(userRole.getRoleId());
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        // 返回UserDetails實現類
        return new User(user.getName(), user.getPassword(), authorities);
    }
}

1.3自定義WebSecurityConfigurerAdapter的子類進行自定義登錄認證配置

Spring Security基於表單的身份驗證是WebSecurityConfigurerAdapter在configure(HttpSecurity http)方法中提供了一個默認配置,我們可通過自定義其子類WebSecurityConfig,實現自己的表單驗證登錄配置。
默認配置

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated() 1
            .and()
        .formLogin() 2
            .and()
        .httpBasic(); 3
}
  1. 確保對我們的應用程序的任何請求都要求用戶進行身份驗證
  2. 允許用戶使用基於表單的登錄進行身份驗證
  3. 允許用戶使用HTTP基本身份驗證進行身份驗證

雖然自動生成的登錄頁面便於快速啟動和運行,但大多數應用程序都希望提供自己的登錄頁面。為此,我們可以更新我們的配置,如下所示:

protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login") 1
            .permitAll();        2
}
  1. 更新的配置指定登錄頁面的位置。
  2. 我們必須授予所有用戶(即未經身份驗證的用戶)訪問我們的登錄頁面的權限。formLogin().permitAll()方法允許為與基於表單的登錄相關聯的所有URL授予對所有用戶的訪問權限。
    我們可以通過向http.authorizeRequests()方法添加多個子項來指定網址的自定義要求。例如:
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()                                                                1
            .antMatchers("/resources/**", "/signup", "/about").permitAll()                  2
            .antMatchers("/admin/**").hasRole("ADMIN")                                      3
            .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")            4
            .anyRequest().authenticated()                                                   5
            .and()
        // ...
        .formLogin();
}
  1. http.authorizeRequests()方法有多個子項,每個匹配器按其聲明的順序進行考慮。
  2. 我們指定了任何用戶都可以訪問的多種URL模式。具體來說,如果URL以“/ resources /”開頭,等於“/ signup”或等於“/ about”,則任何用戶都可以訪問請求。
  3. 任何以“/ admin /”開頭的URL都將僅限於具有“ROLE_ADMIN”角色的用戶。您會注意到,由於我們正在調用hasRole方法,因此我們不需要指定“ROLE_”前綴。
  4. 任何以“/ db /”開頭的URL都要求用戶同時擁有“ROLE_ADMIN”和“ROLE_DBA”。您會注意到,由於我們使用的是hasRole表達式,因此我們不需要指定“ROLE_”前綴。
  5. 任何尚未匹配的URL只需要對用戶進行身份驗證

使用WebSecurityConfigurerAdapter時,會自動應用注銷功能。默認情況下,訪問URL /logout將通過以下方式記錄用戶:

  • 使HTTP會話無效
  • 清理已配置的任何RememberMe身份驗證
  • 清除SecurityContextHolder
  • 重定向到/login?logout

但是,與配置登錄功能類似,您還可以使用各種選項來進一步自定義注銷要求:

protected void configure(HttpSecurity http) throws Exception {
    http
        .logout()                                                                1
            .logoutUrl("/my/logout")                                                 2
            .logoutSuccessUrl("/my/index")                                           3
            .logoutSuccessHandler(logoutSuccessHandler)                              4
            .invalidateHttpSession(true)                                             5
            .addLogoutHandler(logoutHandler)                                         6
            .deleteCookies(cookieNamesToClear)                                       7
            .and()
        ...
}
  1. 提供注銷支持。使用WebSecurityConfigurerAdapter時會自動應用此選項。
  2. 觸發注銷的URL(默認為/logout)。如果啟用了CSRF保護(默認),則該請求也必須是POST。
  3. 注銷后重定向到的URL。默認值為/login?logout。
  4. 我們指定一個自定義LogoutSuccessHandler。如果指定了此項,則忽略logoutSuccessUrl()。
  5. 指定在注銷時是否使HttpSession無效。默認情況下這是真的。
  6. 添加LogoutHandler。默認情況下,SecurityContextLogoutHandler被添加為最后一個LogoutHandler。
  7. 允許指定在注銷成功時刪除的cookie的名稱。這是顯式添加CookieClearingLogoutHandler的快捷方式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM