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