總結之Spring boot集成Spring security四部曲

一人得道雞犬升天

得益於springboot起步依賴、自動配置,spring security在繁雜的配置中解脫出來,一個重量級安全框架重換新生。
我們看看springboot中spring security玩法,spring cloud也是一脈相承呀。

第一步曲~初探

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

我們加入依賴後便使用起來了security,系統生成隨機密碼。
在這裏插入圖片描述
我們的請求就被攔截了
在這裏插入圖片描述
1:自定義密碼
application.yml
String:
application:
name: rabbitmq_cons_demo
security:
user:
name:admin
password:123456
2:權限處理
java代碼在內存中配置
新建Security 核心配置類繼承WebSecurityConfigurerAdapter

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.io.PrintWriter;

/**
 * @author liuzonghua
 * @Package com.example.
 * @Description:
 * @date 2020/5/7 9:26
 */
@Configuration
@EnableWebSecurity // 啓用Spring Security的Web安全支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 將用戶設置在內存中
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void config(AuthenticationManagerBuilder auth) throws Exception {
        // 在內存中配置用戶,配置多個用戶調用`and()`方法
        auth.inMemoryAuthentication()
                .passwordEncoder(passwordEncoder()) // 指定加密方式
                .withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN")
                .and()
                .withUser("test").password(passwordEncoder().encode("123456")).roles("USER");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速實現加密加鹽
        return new BCryptPasswordEncoder();
    }

    /**
     * 登錄處理
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 開啓登錄配置
        http.authorizeRequests()
                // 標識訪問 `/index` 這個接口,需要具備`ADMIN`角色
                .antMatchers("/index").hasRole("ADMIN")
                // 允許匿名的url - 可理解爲放行接口 - 多個接口使用,分割
                .antMatchers("/", "/home").permitAll()
                // 其餘所有請求都需要認證
                .anyRequest().authenticated()
                .and()
                // 設置登錄認證頁面
                .formLogin().loginPage("/login")
                // 登錄成功後的處理接口 - 方式①
                .loginProcessingUrl("/home")
                // 自定義登陸用戶名和密碼屬性名,默認爲 username和password
                .usernameParameter("username")
                .passwordParameter("password")
                // 登錄成功後的處理器  - 方式②
//                .successHandler((req, resp, authentication) -> {
//                    resp.setContentType("application/json;charset=utf-8");
//                    PrintWriter out = resp.getWriter();
//                    out.write("登錄成功...");
//                    out.flush();
//                })
                // 配置登錄失敗的回調
                .failureHandler((req, resp, exception) -> {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("登錄失敗...");
                    out.flush();
                })
                .permitAll()//和表單登錄相關的接口統統都直接通過
                .and()
                .logout().logoutUrl("/logout")
                // 配置註銷成功的回調
                .logoutSuccessHandler((req, resp, authentication) -> {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("註銷成功...");
                    out.flush();
                })
                .permitAll()
                .and()
                .httpBasic()
                .and()
                // 關閉CSRF跨域
                .csrf().disable();

    }

    /**
     * 忽略攔截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 設置攔截忽略url - 會直接過濾該url - 將不會經過Spring Security過濾器鏈
        web.ignoring().antMatchers("/getUserInfo");
        // 設置攔截忽略文件夾,可以對靜態資源放行
        web.ignoring().antMatchers("/css/**", "/js/**");
    }
}

第二步曲~自定義登錄認證處理

配置用戶密碼校驗過濾器

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 用戶密碼校驗過濾器
     */
    private final AdminAuthenticationProcessingFilter adminAuthenticationProcessingFilter;

    public SecurityConfig(AdminAuthenticationProcessingFilter adminAuthenticationProcessingFilter) {
        this.adminAuthenticationProcessingFilter = adminAuthenticationProcessingFilter;
    }

    /**
     * 權限配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.antMatcher("/**").authorizeRequests();

        // 禁用CSRF 開啓跨域
        http.csrf().disable().cors();

        // 登錄處理 - 前後端一體的情況下
//        registry.and().formLogin().loginPage("/login").defaultSuccessUrl("/").permitAll()
//                // 自定義登陸用戶名和密碼屬性名,默認爲 username和password
//                .usernameParameter("username").passwordParameter("password")
//                // 異常處理
//                .failureUrl("/login/error").permitAll()
//                // 退出登錄
//                .and().logout().permitAll();

        // 標識只能在 服務器本地ip[127.0.0.1或localhost] 訪問`/home`接口,其他ip地址無法訪問
        registry.antMatchers("/home").hasIpAddress("127.0.0.1");
        // 允許匿名的url - 可理解爲放行接口 - 多個接口使用,分割
        registry.antMatchers("/login", "/index").permitAll();
        // OPTIONS(選項):查找適用於一個特定網址資源的通訊選擇。 在不需執行具體的涉及數據傳輸的動作情況下, 允許客戶端來確定與資源相關的選項以及 / 或者要求, 或是一個服務器的性能
        registry.antMatchers(HttpMethod.OPTIONS, "/**").denyAll();
        // 自動登錄 - cookie儲存方式
        registry.and().rememberMe();
        // 其餘所有請求都需要認證
        registry.anyRequest().authenticated();
        // 防止iframe 造成跨域
        registry.and().headers().frameOptions().disable();

        // 自定義過濾器認證用戶名密碼
        http.addFilterAt(adminAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章