面试必备技能,springsecurity
如果用戶通過Spring Security進行登錄,通常會涉及到以下四個類,并按照如下順序進行處理:
1.WebSecurityConfigurerAdapter:首先會調用WebSecurityConfigurerAdapter中的configure(HttpSecurity http)方法,用于配置哪些URL需要被攔截,哪些URL不需要被攔截。如果用戶訪問一個受保護的URL,則Spring Security會重定向到登錄頁面。
2.UserDetailsService:當用戶填寫登錄表單并點擊“登錄”按鈕時,Spring Security會將表單中的用戶名和密碼傳遞給UserDetailsService類,以便驗證用戶是否有效。如果用戶信息是有效的,該方法會返回一個實現了UserDetails接口的對象,表示已驗證的用戶。
3.AuthorizationServerConfigurerAdapter:如果用戶信息是有效的,則Spring Security會創建一個OAuth2令牌并將其發送給客戶端。這一步驟涉及到AuthorizationServerConfigurerAdapter類,其中定義了授權服務器的詳細信息,包括客戶端ID、客戶端密鑰、授權類型等等。
4.TokenConfig:最后,Spring Security會使用TokenConfig類來設置令牌的存儲方式、過期時間等其他配置細節。在該類中,我們可以指定使用哪種TokenStore、TokenEnhancer等。
.總之,以上四個步驟結合在一起,可以實現用戶認證和授權,并生成一個OAuth2令牌,一般都會使用jwt令牌來替代OAuth2令牌。
JWT是一個基于JSON格式的令牌,其中包含了關于用戶、授權和其他元數據的聲明。JWT可以使用私鑰進行簽名,確保其完整性和真實性,還可以使用公鑰進行驗證。由于JWT是自包含的,因此它們可以在不同系統之間輕松地傳遞,并且可以存儲在客戶端中而無需依賴服務器。另外,由于JWT已經被簽名,所以它們通常不需要與授權服務器通信來驗證其有效性,這使得JWT更具擴展性和靈活性
模塊該如何吃透
權限認證
1,功能實現
業務功能實現:用戶名密碼登錄、二維碼登錄,第三方用戶登錄、手機短信登錄、用戶、角色、權限管理和分配
●技術方案支撐:RBAC模型、Spring Security 或Apache Shiro
2,常見的問題
token刷新問題、密碼的加密和解密、XSS防跨站攻擊
3,權限系統設計
可擴展性、高可用性、通用性
手機短信登錄
@PostMapping("/sendMsg")public R<String> sendMsg(@RequestBody User user, HttpSession session){//獲取手機號String phone = user.getPhone();if(StringUtils.isNotEmpty(phone)){//生成隨機的4位驗證碼String code = ValidateCodeUtils.generateValidateCode(4).toString();log.info("code={}",code);//調用阿里云提供的短信服務API完成發送短信//SMSUtils.sendMessage("瑞吉外賣","",phone,code);//將生成的驗證碼緩存到Redis中,并且設置有效期為5分鐘redisTemplate.opsForValue().set(phone,code,5,TimeUnit.MINUTES);return R.success("手機驗證碼短信發送成功");}return R.error("短信發送失敗");} import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.profile.DefaultProfile;/*** 短信發送工具類*/ public class SMSUtils {/*** 發送短信* @param signName 簽名* @param templateCode 模板* @param phoneNumbers 手機號* @param param 參數*/public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");IAcsClient client = new DefaultAcsClient(profile);SendSmsRequest request = new SendSmsRequest();request.setSysRegionId("cn-hangzhou");request.setPhoneNumbers(phoneNumbers);request.setSignName(signName);request.setTemplateCode(templateCode);request.setTemplateParam("{\"code\":\""+param+"\"}");try {SendSmsResponse response = client.getAcsResponse(request);System.out.println("短信發送成功");}catch (ClientException e) {e.printStackTrace();}}}第三方登錄流程(以QQ登錄其他系統為例子)
1.第三方QQ用戶發起登錄請求:當第三方QQ用戶選擇使用QQ登錄我們的系統時,用戶通過點擊相關登錄鏈接或按鈕觸發登錄請求。
2.跳轉至QQ登錄頁面:系統將生成一個包含授權請求的URL,并將用戶重定向到QQ的登錄頁面。用戶在該頁面進行QQ賬號的登錄驗證。
3.用戶授權:登錄成功后,QQ向用戶展示所需授權信息的權限列表,用戶同意授權請求,允許我們的系統訪問其相關信息。
4.獲取授權憑證code:QQ登錄頁面在用戶授權成功后,將會將一個授權憑證code返回給我們的系統。該code是臨時有效的,通常只能使用一次。
5.后端獲取access token:我們的系統收到QQ返回的授權憑證code后,使用該code與QQ的授權服務器交互,并通過OAuth2協議獲取訪問令牌(access token)。此令牌用于后續對QQ API的調用進行認證。
6.獲取用戶信息:系統使用獲得的access token與QQ的API服務器通信,請求獲取用戶的相關信息,如昵稱、頭像等。
7.驗證用戶身份:獲取到用戶信息后,系統可以根據自身業務邏輯對用戶進行驗證。此時可以使用Spring Security提供的UserDetailsService接口實現,該接口負責從數據庫或其他數據源中獲取用戶的詳細信息。
8.生成JWT令牌:如果用戶已在系統中注冊并通過驗證,系統會生成一個JWT令牌。這里可以利用UserDetailsService從數據庫中獲取的用戶信息,包括用戶名、角色等,進行令牌的生成和簽名。
9.返回JWT令牌:系統將生成的JWT令牌返回給前端客戶端。客戶端可以將令牌存儲在Cookie或本地存儲中,以便后續請求時攜帶。
10.后續請求的認證與授權:在用戶完成登錄后,其后續的請求將攜帶JWT令牌作為身份憑證。每次請求到達后端時,Spring Security會使用配置的JWT驗證器來驗證令牌的有效性,并從令牌中提取用戶信息。
11.UserDetailsService的使用:在驗證過程中,Spring Security使用UserDetailsService接口來加載用戶的詳細信息。該接口包含loadUserByUsername方法,通過用戶名從數據庫或其他數據源中加載用戶信息。
token刷新問題,可以直接通過配置來解決
1.導入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency>2.新建配置類TokenConfig
//令牌管理服務 public class TokenConfig @Bean(name="authorizationServerTokenServicesCustom") public AuthorizationServerTokenServices tokenService() {DefaultTokenServices service=new DefaultTokenServices();service.setSupportRefreshToken(true);//支持刷新令牌service.setTokenStore(tokenStore);//令牌存儲策略TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));service.setTokenEnhancer(tokenEnhancerChain);service.setAccessTokenValiditySeconds(7200); // 令牌默認有效期2小時service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默認有效期3天return service; }密碼的加密和密碼匹配
在WebSecurityConfigurerAdapter的子類中加入
@Autowired
PasswordEncoder passwordEncoder;
boolean matches = passwordEncoder.matches(inputPassword, password);
XSS防跨站攻擊
XSS(跨站腳本攻擊)是一種常見的Web應用程序安全漏洞,攻擊者通過在受害者訪問的網頁中注入惡意腳本,從而達到獲取用戶敏感信息、竊取cookie等目的。
其中一個常見的方法是使用Thymeleaf等前端模板引擎,在顯示用戶輸入內容時對其進行轉義,以防止惡意腳本的注入。在Spring Security中,可以通過配置HttpSecurity對象來啟用XSS保護機制,例如:
//WebSecurityConfig @Override protected void configure(HttpSecurity http) throws Exception {http.headers().xssProtection().block(true).xssProtectionEnabled(true); }這將啟用瀏覽器內置的XSS保護機制,如果檢測到惡意腳本,則會自動將其阻止。
另外,Spring Security還提供了許多其他的安全策略和配置選項,如使用Content-Security-Policy(CSP)來限制頁面中可執行的腳本來源,使用HttpOnly屬性來限制cookie的訪問權限等。這些機制可以幫助保護Web應用程序免受XSS攻擊。
jwt令牌springsecurity框架默認會校驗有無令牌和令牌的合法性
每次都會攜帶令牌,可以通過一下獲得(令牌一般都會擴展存儲一些用戶信息)Object principalObj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();if (principalObj instanceof String) {//取出用戶身份信息String principal = principalObj.toString();//將json轉成對象XcUser user = JSON.parseObject(principal, XcUser.class);return user;}但是有一些業務有的接口需要登錄有的接口不需要登錄就可訪問,如何解決?
/*** @Configuration@EnableResourceServer@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)public class ResouceServerConfig extends ResourceServerConfigurerAdapter*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/r/**","/course/**").authenticated()//所有/r/**的請求必須認證通過.anyRequest().permitAll();//其余放行}RBAC模型,分為資源和角色型(資源性權限擴展性強)
在服務中配置
package com.xuecheng.content.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.TokenStore;/*** @description RBAC資源服務配置* @author Mr.M* @date 2022/10/18 16:33* @version 1.0*/@Configuration@EnableResourceServer@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)public class ResouceServerConfig extends ResourceServerConfigurerAdapter {/****///資源服務標識public static final String RESOURCE_ID = "xuecheng-plus";@AutowiredTokenStore tokenStore;@Overridepublic void configure(ResourceServerSecurityConfigurer resources) {resources.resourceId(RESOURCE_ID)//資源 id.tokenStore(tokenStore).stateless(true);}@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests() // .antMatchers("/r/**","/course/**").authenticated()//所有/r/**的請求必須認證通過.anyRequest().permitAll();//其余放行} //RBAC角色服務配置 // @Override // public void configure(HttpSecurity http) throws Exception { // http.authorizeRequests() // .antMatchers("/api/admin/**").hasRole("ADMIN") // .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN") // .anyRequest().authenticated(); // }}總結
以上是生活随笔為你收集整理的面试必备技能,springsecurity的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM学习(七):运行时数据区(精讲)
- 下一篇: 如何让AI智能语音助手更加智能