Java框架-SpringBoot

1. 概述

1.1 是什麼

答:SpringBoot是Spring組件的一站式解決方案,並不是獨立框架,是用來簡化Spring配置,提供各種啓動器,讓開發者能快速上手的。

1.2 優點

  • 容易上手,開箱即用,提升開發效率;
  • 能和Spring生態系統集成;
  • 遵循默認配置,提供了一系列通用的非業務性功能;
  • 內置http服務器,如tomcat、jetty,開發web應用更加輕鬆;
  • maven配置直接寫入,有效避免衝突。

1.3 Spring Boot Starters

答:Spring Boot Starters是一系列依賴關係的集合。

  • 內部提供了XXXAutoConfiguration的自動化配置類;
  • 通過條件註解來決定一個配置是否生效,同時提供一系列的默認配置
  • 之後通過類型安全的屬性注入將這些配置屬性注入容器,新注入的屬性會代替掉默認屬性。

1.4 核心註解

答:@SpringBootApplication可以看作是由三個註解的集合。

  • @SpringBootConfiguration:組合了 @Configuration 註解,實現配置文件的功能,允許在上下文註冊bean。
  • @EnableAutoConfiguration:打開自動配置的功能。
  • @ComponentScan:掃描@Component(@Server,@Controller)的bean。

1.5 jar包區別

答:Spring Boot打包成的jar是可執行的,通過 java -jar xxx.jar 命令運行,不能作爲普通的jar包被項目依賴使用。

  • Spring Boot的jar包解壓後,代碼在\BOOT-INF\classes 目錄下。
  • 可以在pom.xml文件中增加配置,將項目打包成兩個jar ,一個可執行,一個可引用。

2. 配置

2.1 自動配置

答:自動配置的核心就是@EnableAutoConfiguration, @Conditional註解。

  1. @EnableAutoConfiguration,通過@Import註解導入自動配置方法類AutoConfigurationImportSelector。該類中將所有自動配置類信息以list返回,同時被容器當作bean管理。(META-INF/spring.factories文件)
  2. @Conditional,類似if條件爲true就執行後續,如@ConditionalClass指定類必須存在類路徑下,@ConditionalOnBean容器中有指定Bean。

總結:EnableAutoConfiguration實現配置信息的導入,Conditional用來指定此類需要的配置信息。

2.2 配置加載方式

答:properties文件,yaml文件,系統環境變量,命令行參數。

2.3 Yaml

2.3.1 概述

答:yaml是一種可讀性友好的數據序列化語言,常用來作爲配置文件。

2.3.2 優點

答:配置有序;支持數組;簡潔結構化。但不支持註解導入自定義的yaml配置。

3. 安全

3.1 Spring Security

答:官方提供的安全管理框架,添加依賴後,項目的所有接口都被保護,必須登陸後才能訪問。通過繼承WebSecurityConfigurerAdapter接口,實現登錄配置、密碼加密、攔截訪問等等一系列功能。

@Override
protected void configure(HttpSecurity http) throws Exception {
    //開啓登陸配置
    http.authorizeRequests()
            //訪問/hello接口,且有admin的角色
            .antMatchers("/hello").hasRole("admin")
            //剩餘其他接口,登錄後就能訪問
            .anyRequest().authenticated()
            .and()
            .formLogin()
            //定義登錄頁面,未登錄時自動跳轉
            .loginPage("/login")
            .loginProcessingUrl("/doLogin")
            //登錄時用戶名和密碼的key,可以自定義
            .usernameParameter("uname")
            .passwordParameter("passwd")
            //登錄成功的處理器
            .successHandler(new AuthenticationSuccessHandler() {
                @Override
                public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write("success");
                    out.flush();
                    out.close();
                }
            })
            //登錄失敗的處理器
            .failureHandler(new AuthenticationFailureHandler() {
                @Override
                public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    Map<String, Object> map = new HashMap<>();
                    //相關異常去AuthenticException中查找子類
                    if (e instanceof LockedException) {
                        map.put("msg", "賬戶鎖定");
                    } else if (e instanceof BadCredentialsException) {
                        map.put("msg", "輸入錯誤");
                    } else {
                        map.put("msg", "登錄失敗");
                    }
                    out.write(new ObjectMapper().writeValueAsString(map));
                    out.flush();
                    out.close();
                }
            })
            //和表單登錄相關接口直接通過
            .permitAll()
            .and()
            //登出註銷配置
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler(new LogoutSuccessHandler() {
                @Override
                public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter out = httpServletResponse.getWriter();
                    out.write("success");
                    out.flush();
                }
            })
            .permitAll()
            .and()
            .httpBasic()
            .and()
            .csrf()
            .disable();
}

3.2 跨域問題

3.2.1 CSRF

答:CSRF跨站請求僞造,通過僞裝成受信任用戶進行請求獲取數據。CSRF通過冒用cookie實現,利用網站對Client的信任。

3.2.2 CORS

答:瀏覽器基於安全考慮有同源策略,規定域名端口協議一致,CORS跨域資源共享就是爲了避開同源策略。通過繼承WebMvcConfigurer重寫addCorsMappings()實現。

3.2.3 其餘方案

  • Referer字段驗證:不適用,Referer能被篡改。HTTP頭中用Referer字段記錄請求的源地址。
  • Token驗證:Server發給Client一個Token,Client發出帶Token的請求,若Token不合法,則Server拒絕請求。
  • 雙重Cookie驗證:Client將Cookie參數加入請求參數中,Server校驗,若無附加的cookie參數則拒絕請求。
  • 驗證碼:在用戶進行敏感操作時,要求用戶輸入驗證碼。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章