Spring Security 基礎教程 -- HttpSecurity 權限和登錄表單配置


HttpSecurity 權限配置

主要是通過 HttpSecurity 配置訪問控制權限,它仍是繼承自 WebSecurityConfigurerAdapter ,重寫其中的 configure(HttpSecurity http) 方法, 沿用上面的 SecurityConfig 類

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 這是一個過期的方法
     * 指明密碼不用加密
     */
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 定義兩個用戶,並設置密碼和角色
     * 從 Spring5.0 開始,密碼必須要加密
     * 基於內存的用戶認證
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("123456")
                .roles("admin")
                .and()
                .withUser("user1")
                .password("123")
                .roles("user");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 只有 admin 角色才能訪問路徑 /admin/**
                .antMatchers("/admin/**").hasRole("admin")
                // admin 和 user 角色都能訪問路徑 /user/**
                .antMatchers("/user/**").hasAnyRole("admin", "user")
                // 其他路徑請求,只要是登錄用戶都可以訪問
                .anyRequest().authenticated()
                .and()
                // 配置表單登錄
                .formLogin()
                // 處理登錄的 URL
                .loginProcessingUrl("/doLogin")
                // 與登錄相關的請求都可以通過
                .permitAll()
                .and()
                // 關閉 csrf 保護
                .csrf().disable();
    }
}

通過 http.authorizeRequests().antMatchers("路徑").hasRole("角色") ,賦予相應角色的路徑訪問權限。

HttpSecurity 登錄表單配置

仍然沿用上面的configure(HttpSecurity http)方法。

登錄成功

在前后端分離的項目中,登錄成功后,后台向前台返回一個 json 字符串,表示登錄成功,具體配置如下:

                // 登錄成功后的處理
                .successHandler(new AuthenticationSuccessHandler() {
                    // authentication 保存了登錄成功的用戶信息
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        // 返回 json 格式的數據
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter writer = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<>(16);
                        map.put("status:", 200);
                        map.put("msg:",authentication.getPrincipal());
                        writer.write(new ObjectMapper().writeValueAsString(map));
                        writer.flush();
                        writer.close();
                    }
                })

效果如下圖:

登錄失敗

登錄失敗后,后台仍向前台返回一個 json 字符串,並注明登錄失敗的原因。

登錄失敗后的具體配置如下:

                //登錄失敗后的處理
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter writer = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<>(16);
                        map.put("status:", 401);
                        if (e instanceof LockedException) {
                            map.put("msg:", "賬戶被鎖定,登錄失敗!");
                        }else if (e instanceof BadCredentialsException){
                            map.put("msg:", "用戶名或密碼輸入錯誤,登錄失敗");
                        }else if (e instanceof DisabledException){
                            map.put("msg:", "賬戶被禁用,登錄失敗!");
                        }else if (e instanceof AccountExpiredException){
                            map.put("msg:", "賬戶過期,登錄失敗!");
                        }else if (e instanceof CredentialsExpiredException){
                            map.put("msg:", "密碼過期,登錄失敗");
                        }else {
                            map.put("msg:","登錄失敗!");
                        }
                        writer.write(new ObjectMapper().writeValueAsString(map));
                        writer.flush();
                        writer.close();
                    }
                })

效果如下:

對於登錄失敗后的各種情況,可以通過查看抽象類 AuthenticationException的繼承關系,獲悉所有的異常情況:

注銷登錄

仍然沿用上面的configure(HttpSecurity http)方法。

.permitAll()方法后,配置注銷登錄的信息:

                // 與登錄相關的請求都可以通過
                .permitAll()
                // 注銷登錄的配置
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        // 返回 json 格式的數據
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter writer = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<>(16);
                        map.put("status:", 200);
                        map.put("msg:","注銷登錄成功!");
                        writer.write(new ObjectMapper().writeValueAsString(map));
                        writer.flush();
                        writer.close();
                    }
                })

注銷登錄是一個 get 請求,效果如下:

每天學習一點點,每天進步一點點。


免責聲明!

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



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