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註解。
- @EnableAutoConfiguration,通過@Import註解導入自動配置方法類AutoConfigurationImportSelector。該類中將所有自動配置類信息以list返回,同時被容器當作bean管理。(META-INF/spring.factories文件)
- @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參數則拒絕請求。
- 驗證碼:在用戶進行敏感操作時,要求用戶輸入驗證碼。