<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從零入門(mén) SpringSecurity

          共 13479字,需瀏覽 27分鐘

           ·

          2022-01-19 14:35

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??

          來(lái)源:juejin.cn/post/7026734817853210661

          今天來(lái)一篇 Spring Security 精講,相信你看過(guò)之后能徹底搞懂 Spring Security。

          Spring Security簡(jiǎn)介

          Spring Security 是一種高度自定義的安全框架,利用(基于)SpringIOC/DI和AOP功能,為系統(tǒng)提供了聲明式安全訪(fǎng)問(wèn)控制功能,「減少了為系統(tǒng)安全而編寫(xiě)大量重復(fù)代碼的工作」

          「核心功能:認(rèn)證和授權(quán)」

          Spring Security 認(rèn)證流程

          SpringSecurity認(rèn)證執(zhí)行流程

          Spring Security 項(xiàng)目搭建

          導(dǎo)入依賴(lài)

          Spring Security已經(jīng)被Spring boot進(jìn)行集成,使用時(shí)直接引入啟動(dòng)器即可

          <dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-securityartifactId>
          dependency>

          訪(fǎng)問(wèn)頁(yè)面

          導(dǎo)入spring-boot-starter-security啟動(dòng)器后,Spring Security已經(jīng)生效,默認(rèn)攔截全部請(qǐng)求,如果用戶(hù)沒(méi)有登錄,跳轉(zhuǎn)到內(nèi)置登錄頁(yè)面。

          在瀏覽器輸入:http://localhost:8080/ 進(jìn)入Spring Security內(nèi)置登錄頁(yè)面

          用戶(hù)名:user。

          密碼:項(xiàng)目啟動(dòng),打印在控制臺(tái)中。

          自定義用戶(hù)名和密碼

          修改「application.yml」 文件

          #?靜態(tài)用戶(hù),一般只在內(nèi)部網(wǎng)絡(luò)認(rèn)證中使用,如:內(nèi)部服務(wù)器1,訪(fǎng)問(wèn)服務(wù)器2
          spring:
          ??security:
          ????user:
          ??????name:?test??#?通過(guò)配置文件,設(shè)置靜態(tài)用戶(hù)名
          ??????password:?test?#?配置文件,設(shè)置靜態(tài)登錄密碼

          UserDetailsService詳解

          什么也沒(méi)有配置的時(shí)候,賬號(hào)和密碼是由Spring Security定義生成的。而在實(shí)際項(xiàng)目中賬號(hào)和密碼都是從數(shù)據(jù)庫(kù)中查詢(xún)出來(lái)的。所以我們要通過(guò)「自定義邏輯控制認(rèn)證邏輯」。如果需要自定義邏輯時(shí),只需要實(shí)現(xiàn)UserDetailsService接口

          @Component
          public?class?UserSecurity?implements?UserDetailsService?{

          ????@Autowired
          ????private?UserService?userService;

          ????@Override
          ????public?UserDetails?loadUserByUsername(String?userName)?throws?UsernameNotFoundException?{

          ????????User?user?=?userService.login(userName);
          ????????System.out.println(user);
          ????????if?(null==user){
          ????????????throw?new?UsernameNotFoundException("用戶(hù)名錯(cuò)誤");
          ????????}
          ????????org.springframework.security.core.userdetails.User?result?=
          ????????????????new?org.springframework.security.core.userdetails.User(
          ????????????????????????userName,user.getPassword(),?AuthorityUtils.createAuthorityList()
          ????????????????);
          ????????return?result;
          ????}

          }

          PasswordEncoder密碼解析器詳解

          PasswordEncoder

          「PasswordEncoder」 是SpringSecurity 的密碼解析器,用戶(hù)密碼校驗(yàn)、加密 。自定義登錄邏輯時(shí)要求必須給容器注入PaswordEncoder的bean對(duì)象

          SpringSecurity 定義了很多實(shí)現(xiàn)接口「PasswordEncoder」 滿(mǎn)足我們密碼加密、密碼校驗(yàn) 使用需求。

          PasswordEncoder密碼解析器詳解

          自定義密碼解析器

          1. 編寫(xiě)類(lèi),實(shí)現(xiàn)PasswordEncoder 接口
          /**
          ?*?憑證匹配器,用于做認(rèn)證流程的憑證校驗(yàn)使用的類(lèi)型
          ?*?其中有2個(gè)核心方法
          ?*?1.?encode?-?把明文密碼,加密成密文密碼
          ?*?2.?matches?-?校驗(yàn)明文和密文是否匹配
          ?*?*/

          public?class?MyMD5PasswordEncoder?implements?PasswordEncoder?{

          ????/**
          ?????*?加密
          ?????*?@param?charSequence??明文字符串
          ?????*?@return
          ?????*/

          ????@Override
          ????public?String?encode(CharSequence?charSequence)?{
          ????????try?{
          ????????????MessageDigest?digest?=?MessageDigest.getInstance("MD5");
          ????????????return?toHexString(digest.digest(charSequence.toString().getBytes()));
          ????????}?catch?(NoSuchAlgorithmException?e)?{
          ????????????e.printStackTrace();
          ????????????return?"";
          ????????}
          ????}

          ????/**
          ?????*?密碼校驗(yàn)
          ?????*?@param?charSequence?明文,頁(yè)面收集密碼
          ?????*?@param?s?密文?,數(shù)據(jù)庫(kù)中存放密碼
          ?????*?@return
          ?????*/

          ????@Override
          ????public?boolean?matches(CharSequence?charSequence,?String?s)?{
          ????????return?s.equals(encode(charSequence));
          ????}

          ?????/**
          ?????*?@param?tmp?轉(zhuǎn)16進(jìn)制字節(jié)數(shù)組
          ?????*?@return?飯回16進(jìn)制字符串
          ?????*/

          ????private?String?toHexString(byte?[]?tmp){
          ????????StringBuilder?builder?=?new?StringBuilder();
          ????????for?(byte?b?:tmp){
          ????????????String?s?=?Integer.toHexString(b?&?0xFF);
          ????????????if?(s.length()==1){
          ????????????????builder.append("0");
          ????????????}
          ????????????builder.append(s);
          ????????}

          ????????return?builder.toString();

          ????}
          }

          2.在配置類(lèi)中指定自定義密碼憑證匹配器

          /**
          ??*?加密
          ??*?@return?加密對(duì)象
          ??*?如需使用自定義密碼憑證匹配器?返回自定義加密對(duì)象
          ??*?例如:?return?new?MD5PasswordEncoder();?
          ??*/

          @Bean
          public?PasswordEncoder?passwordEncoder()?{
          ????return?new?BCryptPasswordEncoder();?//Spring?Security?自帶
          }

          登錄配置

          方式一 轉(zhuǎn)發(fā)

          http.formLogin()
          ????.usernameParameter("name")?//?設(shè)置請(qǐng)求參數(shù)中,用戶(hù)名參數(shù)名稱(chēng)。?默認(rèn)username
          ????.passwordParameter("pswd")?//?設(shè)置請(qǐng)求參數(shù)中,密碼參數(shù)名稱(chēng)。?默認(rèn)password
          ????.loginPage("/toLogin")?//?當(dāng)用戶(hù)未登錄的時(shí)候,跳轉(zhuǎn)的登錄頁(yè)面地址是什么??默認(rèn)?/login
          ????.loginProcessingUrl("/login")?//?用戶(hù)登錄邏輯請(qǐng)求地址是什么。?默認(rèn)是?/login
          ????.failureForwardUrl("/failure");?//?登錄失敗后,請(qǐng)求轉(zhuǎn)發(fā)的位置。Security請(qǐng)求轉(zhuǎn)發(fā)使用Post請(qǐng)求。默認(rèn)轉(zhuǎn)發(fā)到:loginPage?error
          ????.successForwardUrl("/toMain");?//?用戶(hù)登錄成功后,請(qǐng)求轉(zhuǎn)發(fā)到的位置。Security請(qǐng)求轉(zhuǎn)發(fā)使用POST請(qǐng)求。

          方式二 :重定向

          http.formLogin()
          ????.usernameParameter("name")?//?設(shè)置請(qǐng)求參數(shù)中,用戶(hù)名參數(shù)名稱(chēng)。?默認(rèn)username
          ????.passwordParameter("pswd")?//?設(shè)置請(qǐng)求參數(shù)中,密碼參數(shù)名稱(chēng)。?默認(rèn)password
          ????.loginPage("/toLogin")?//?當(dāng)用戶(hù)未登錄的時(shí)候,跳轉(zhuǎn)的登錄頁(yè)面地址是什么??默認(rèn)?/login
          ????.loginProcessingUrl("/login")?//?用戶(hù)登錄邏輯請(qǐng)求地址是什么。?默認(rèn)是?/login
          ?.defaultSuccessUrl("/toMain",true);?//用戶(hù)登錄成功后,響應(yīng)重定向到的位置。GET請(qǐng)求。必須配置絕對(duì)地址。
          ??.failureUrl("/failure");?//?登錄失敗后,重定向的位置。

          方式三:自定義登錄處理器

          自定義登錄失敗邏輯處理器

          /*自定義登錄失敗處理器*/
          public?class?MyAuthenticationFailureHandler?implements?AuthenticationFailureHandler?{
          ????private??String?url;
          ????private?boolean?isRedirect;


          ????public?MyAuthenticationFailureHandler(String?url,?boolean?isRedirect)?{
          ????????this.url?=?url;
          ????????this.isRedirect?=?isRedirect;
          ????}

          ????@Override
          ????public?void?onAuthenticationFailure(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?AuthenticationException?e)?throws?IOException,?ServletException?{
          ????????if?(isRedirect){
          ????????????httpServletResponse.sendRedirect(url);
          ????????}else?{
          ????????????httpServletRequest.getRequestDispatcher(url).forward(httpServletRequest,httpServletResponse);
          ????????}
          ????}

          //get?set?方法?省略

          自定義登錄成功邏輯處理器

          /**
          ?*?自定義登錄成功后處理器
          ?*?轉(zhuǎn)發(fā)重定向,有代碼邏輯實(shí)現(xiàn)
          ?*?*/

          public?class?MyAuthenticationSuccessHandler?implements?AuthenticationSuccessHandler?{
          ????private?String?url;
          ????private?boolean?isRedirect;

          ????public?MyAuthenticationSuccessHandler(String?url,?boolean?isRedirect)?{
          ????????this.url?=?url;
          ????????this.isRedirect?=?isRedirect;
          ????}

          ????/**
          ?????*?@param?request?請(qǐng)求對(duì)象?request.getRequestDispatcher.forward()
          ?????*?@param?response?響應(yīng)對(duì)象?response.sendRedirect()
          ?????*?@param?authentication 用戶(hù)認(rèn)證成功后的對(duì)象。其中報(bào)換用戶(hù)名權(quán)限結(jié)合,內(nèi)容是
          ?????*???????????????????????自定義UserDetailsService
          ?????*?*/

          ????@Override
          ????public?void?onAuthenticationSuccess(HttpServletRequest?request,?HttpServletResponse?response,?Authentication?authentication)?throws?IOException,?ServletException?{
          ????????if?(isRedirect){
          ????????????response.sendRedirect(url);
          ????????}else?{
          ????????????request.getRequestDispatcher(url).forward(request,response);
          ????????}
          ????}

          //get?set?方法?省略???
          http.formLogin()
          ????.usernameParameter("name")?//?設(shè)置請(qǐng)求參數(shù)中,用戶(hù)名參數(shù)名稱(chēng)。?默認(rèn)username
          ????.passwordParameter("pswd")?//?設(shè)置請(qǐng)求參數(shù)中,密碼參數(shù)名稱(chēng)。?默認(rèn)password
          ????.loginPage("/toLogin")?//?當(dāng)用戶(hù)未登錄的時(shí)候,跳轉(zhuǎn)的登錄頁(yè)面地址是什么??默認(rèn)?/login
          ????.loginProcessingUrl("/login")?//?用戶(hù)登錄邏輯請(qǐng)求地址是什么。?默認(rèn)是?/login

          登錄相關(guān)配置類(lèi)

          @Configuration
          @EnableWebSecurity
          public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{

          ????@Autowired
          ????private??UserSecurity?userSecurity;
          ????@Autowired
          ????private?PersistentTokenRepository?persistentTokenRepository;


          ????/**
          ?????*?加密
          ?????*?@return?加密對(duì)象
          ?????*?如需使用自定義加密邏輯?返回自定義加密對(duì)象
          ?????*?return?new?MD5PasswordEncoder();?return?new?SimplePasswordEncoder();
          ?????*/

          ????@Bean
          ????public?PasswordEncoder?passwordEncoder()?{
          ????????return?new?BCryptPasswordEncoder();?//Spring?Security?自帶
          ????}

          ????@Override
          ????protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????????//?配置登錄請(qǐng)求相關(guān)內(nèi)容。
          ????????http.formLogin()
          ????????????.loginPage("/toLogin")?//?當(dāng)用戶(hù)未登錄的時(shí)候,跳轉(zhuǎn)的登錄頁(yè)面地址是什么??默認(rèn)?/login
          ????????????.usernameParameter("name")?//?設(shè)置請(qǐng)求參數(shù)中,用戶(hù)名參數(shù)名稱(chēng)。?默認(rèn)username
          ????????????.passwordParameter("pswd")?//?設(shè)置請(qǐng)求參數(shù)中,密碼參數(shù)名稱(chēng)。?默認(rèn)password
          ????????????.loginProcessingUrl("/login")?//設(shè)置登錄?提交表單數(shù)據(jù)訪(fǎng)問(wèn)請(qǐng)求地址
          ????????????.defaultSuccessUrl("/toMain")???
          ????????????.failureUrl("/toLogin");
          ?????????//.successForwardUrl("/toMain")
          ?????????//.failureForwardUrl("/toLogin");
          ????????????//.successHandler(new?LoginSuccessHandler("/toMain",?true))?//自定義登錄成功處理器
          ????????????????//.failureHandler(new?LoginErrorHandler("/toLogin",?true));

          ????????http.authorizeRequests()
          ????????????//.antMatchers("/toLogin").anonymous()?//只能匿名用戶(hù)訪(fǎng)問(wèn)
          ????????????.antMatchers("/toLogin",?"/register",?"/login",?"/favicon.ico").permitAll()?//?/toLogin請(qǐng)求地址,可以隨便訪(fǎng)問(wèn)。
          ????????????.antMatchers("/**/*.js").permitAll()?//?授予所有目錄下的所有.js文件可訪(fǎng)問(wèn)權(quán)限
          ????????????.regexMatchers(".*[.]css").permitAll()?//?授予所有目錄下的所有.css文件可訪(fǎng)問(wèn)權(quán)限
          ????????????.anyRequest().authenticated();?//?任意的請(qǐng)求,都必須認(rèn)證后才能訪(fǎng)問(wèn)。


          ????????//?配置退出登錄
          ????????http.logout()
          ????????????????.invalidateHttpSession(true)?//?回收HttpSession對(duì)象。退出之前調(diào)用HttpSession.invalidate()?默認(rèn) true
          ????????????????.clearAuthentication(true)?//?退出之前,清空Security記錄的用戶(hù)登錄標(biāo)記。?默認(rèn) true
          ????????????????// .addLogoutHandler()?//?增加退出處理器。
          ????????????????.logoutSuccessUrl("/")?//?配置退出后,進(jìn)入的請(qǐng)求地址。?默認(rèn)是loginPage?logout
          ????????????????.logoutUrl("/logout");?//?配置退出登錄的路徑地址。和頁(yè)面請(qǐng)求地址一致即可。

          ????????//?關(guān)閉CSRF安全協(xié)議。
          ????????//?關(guān)閉是為了保證完整流程的可用。
          ????????http.csrf().disable();
          ????}


          ???@Bean
          ???public?PersistentTokenRepository?persistentTokenRepository(DataSource?dataSource){
          ????????JdbcTokenRepositoryImpl?jdbcTokenRepository?=?new?JdbcTokenRepositoryImpl();
          ????????jdbcTokenRepository.setDataSource(dataSource);
          ????????//jdbcTokenRepository.setCreateTableOnStartup(true);
          ????????return?jdbcTokenRepository;
          ????}
          }

          角色權(quán)限

          ?

          「hasAuthority(String)」 判斷角色是否具有特定權(quán)限

          ?
          http.authorizeRequests().antMatchers("/main1.html").hasAuthority("admin")
          ?

          「hasAnyAuthority(String ...)」 如果用戶(hù)具備給定權(quán)限中某一個(gè),就允許訪(fǎng)問(wèn)

          ?
          http.authorizeRequests().antMatchers("/admin/read").hasAnyAuthority("xxx","xxx")?
          ?

          「hasRole(String)」 如果用戶(hù)具備給定角色就允許訪(fǎng)問(wèn)。否則出現(xiàn)403

          ?
          //請(qǐng)求地址為/admin/read的請(qǐng)求,必須登錄用戶(hù)擁有'管理員'角色才可訪(fǎng)問(wèn)
          http.authorizeRequests().antMatchers("/admin/read").hasRole("管理員")?
          ?

          「hasAnyRole(String ...)」 如果用戶(hù)具備給定角色的任意一個(gè),就允許被訪(fǎng)問(wèn)

          ?
          //用戶(hù)擁有角色是管理員?或?訪(fǎng)客?可以訪(fǎng)問(wèn)?/guest/read
          http.authorizeRequests().antMatchers("/guest/read").hasAnyRole("管理員",?"訪(fǎng)客")
          ?

          「hasIpAddress(String)」 請(qǐng)求是指定的IP就運(yùn)行訪(fǎng)問(wèn)

          ?
          //ip?是127.0.0.1?的請(qǐng)求?可以訪(fǎng)問(wèn)/ip
          http.authorizeRequests().antMatchers("/ip").hasIpAddress("127.0.0.1")

          403 權(quán)限不足頁(yè)面處理

          1.編寫(xiě)類(lèi)實(shí)現(xiàn)接口「AccessDeniedHandler」

          /**
          ?*?@describe??403?權(quán)限不足
          ?*?@author:?AnyWhere
          ?*?@date?2021/4/18?20:57
          ?*/

          @Component
          public?class?MyAccessDeniedHandler?implements?AccessDeniedHandler?{
          ????@Override
          ????public?void?handle(HttpServletRequest?request,?HttpServletResponse?response,?AccessDeniedException?e)?
          ????????????throws?IOException,?ServletException?
          {

          ????????response.setStatus(HttpServletResponse.SC_OK);

          ????????response.setContentType("text/html;charset=UTF-8");

          ????????response.getWriter().write(
          ????????????????""?+
          ????????????????????????""?+
          ????????????????????????""?+
          ????????????????????????"權(quán)限不足,請(qǐng)聯(lián)系管理員"?+
          ????????????????????????"
          "?+
          ????????????????????????""?+
          ????????????????????????""

          ????????);

          ????????response.getWriter().flush();//刷新緩沖區(qū)
          ????}
          }

          2.配置類(lèi)中配置exceptionHandling

          //?配置403訪(fǎng)問(wèn)錯(cuò)誤處理器。
          http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);/

          RememberMe(記住我)

          @Configuration
          @EnableWebSecurity
          public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{
          ??@Override
          ??protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????//配置記住密碼
          ????http.rememberMe()
          ????????.rememberMeParameter("remember-me")?//?修改請(qǐng)求參數(shù)名。?默認(rèn)是remember-me
          ????????.tokenValiditySeconds(14*24*60*60)?//?設(shè)置記住我有效時(shí)間。單位是秒。默認(rèn)是14天
          ????????.rememberMeCookieName("remember-me")?//?修改remember me的cookie名稱(chēng)。默認(rèn)是remember-me
          ????????.tokenRepository(persistentTokenRepository)?//?配置用戶(hù)登錄標(biāo)記的持久化工具對(duì)象。
          ????????.userDetailsService(userSecurity);?//?配置自定義的UserDetailsService接口實(shí)現(xiàn)類(lèi)對(duì)象

          ??}
          ??@Bean
          ??public?PersistentTokenRepository?persistentTokenRepository(DataSource?dataSource){
          ?????JdbcTokenRepositoryImpl?jdbcTokenRepository?=?new?JdbcTokenRepositoryImpl();
          ?????jdbcTokenRepository.setDataSource(dataSource);
          ?????//jdbcTokenRepository.setCreateTableOnStartup(true);
          ?????return?jdbcTokenRepository;
          ??}
          }???

          Spring Security 注解

          @Secured

          ?

          角色校驗(yàn) ,請(qǐng)求到來(lái)訪(fǎng)問(wèn)控制單元方法時(shí)必須包含XX角色才能訪(fǎng)問(wèn)

          角色必須添加ROLE_前綴

          ?
          ??@Secured({"ROLE_管理員","ROLE_訪(fǎng)客"})
          ??@RequestMapping("/toMain")
          ??public?String?toMain(){
          ??????return?"main";
          ??}

          使用注解@Secured需要在配置類(lèi)中添加注解 使@Secured注解生效

          @EnableGlobalMethodSecurity(securedEnabled?=?true)

          @PreAuthorize

          ?

          權(quán)限檢驗(yàn),請(qǐng)求到來(lái)訪(fǎng)問(wèn)控制單元之前必須包含xx權(quán)限才能訪(fǎng)問(wèn),控制單元方法執(zhí)行前進(jìn)行角色校驗(yàn)

          ?
          ???/**
          ?????*?[ROLE_管理員,?admin:read,?admin:write,?all:login,?all:logout,?all:error,?all:toMain]
          ?????*?@PreAuthorize???角色?、權(quán)限?校驗(yàn)?方法執(zhí)行前進(jìn)行角色校驗(yàn)
          ?????*
          ?????*??hasAnyAuthority()?
          ?????*??hasAuthority()
          ?????*
          ?????*??hasPermission()
          ?????*
          ?????*
          ?????*??hasRole()???
          ?????*??hasAnyRole()
          ?????*?*/


          ????@PreAuthorize("hasAnyRole('ROLE_管理員','ROLE_訪(fǎng)客')")
          ????@RequestMapping("/toMain")
          ????@PreAuthorize("hasAuthority('admin:write')")
          ????public?String?toMain(){
          ????????return?"main";
          ????}

          使用@PreAuthorize@PostAuthorize 需要在配置類(lèi)中配置注解@EnableGlobalMethodSecurity 才能生效

          @EnableGlobalMethodSecurity(prePostEnabled?=?true)

          @PostAuthorize

          ?

          權(quán)限檢驗(yàn),請(qǐng)求到來(lái)訪(fǎng)問(wèn)控制單元之后必須包含xx權(quán)限才能訪(fǎng)問(wèn) ,控制單元方法執(zhí)行完后進(jìn)行角色校驗(yàn)

          ?
          ???/**
          ?????*?[ROLE_管理員,?admin:read,?admin:write,?all:login,?all:logout,?all:error,?all:toMain]
          ?????*?@PostAuthorize??角色?、權(quán)限?校驗(yàn)?方法執(zhí)行后進(jìn)行角色校驗(yàn)
          ?????*
          ?????*??hasAnyAuthority()
          ?????*??hasAuthority()
          ?????*??hasPermission()
          ?????*??hasRole()
          ?????*??hasAnyRole()
          ?????*?*/


          ????@PostAuthorize("hasRole('ROLE_管理員')")
          ????@RequestMapping("/toMain")
          ????@PreAuthorize("hasAuthority('admin:write')")
          ????public?String?toMain(){
          ????????return?"main";
          ????}

          Spring Security 整合Thymeleaf 進(jìn)行權(quán)限校驗(yàn)

          <dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-starter-thymeleafartifactId>
          dependency>

          <dependency>
          ?????<groupId>org.thymeleaf.extrasgroupId>
          ?????<artifactId>thymeleaf-extras-springsecurity5artifactId>
          dependency>

          Spring Security中CSRF

          什么是CSRF?

          CSRF(Cross-site request forgery)跨站請(qǐng)求偽造,也被稱(chēng)為“One Click Attack” 或者Session Riding。通過(guò)偽造用戶(hù)請(qǐng)求訪(fǎng)問(wèn)受信任站點(diǎn)的非法請(qǐng)求訪(fǎng)問(wèn)。

          跨域:只要網(wǎng)絡(luò)協(xié)議,ip地址,端口中任何一個(gè)不相同就是跨域請(qǐng)求。

          客戶(hù)端與服務(wù)進(jìn)行交互時(shí),由于http協(xié)議本身是無(wú)狀態(tài)協(xié)議,所以引入了cookie進(jìn)行記錄客戶(hù)端身份。在cookie中會(huì)存放session id用來(lái)識(shí)別客戶(hù)端身份的。在跨域的情況下,session id可能被第三方惡意劫持,通過(guò)這個(gè)session id向服務(wù)端發(fā)起請(qǐng)求時(shí),服務(wù)端會(huì)認(rèn)為這個(gè)請(qǐng)求是合法的,可能發(fā)生很多意想不到的事情。

          通俗解釋?zhuān)?/p>

          CSRF就是別的網(wǎng)站非法獲取我們網(wǎng)站Cookie值,我們項(xiàng)目服務(wù)器是無(wú)法區(qū)分到底是不是我們的客戶(hù)端,只有請(qǐng)求中有Cookie,認(rèn)為是自己的客戶(hù)端,所以這個(gè)時(shí)候就出現(xiàn)了CSRF。

          什么是CSRF

          解決的辦法整體來(lái)說(shuō),就是兩個(gè)思路:

          生成 csrfToken 保存在 HttpSession 或者 Cookie 中。

          請(qǐng)求到來(lái)時(shí),從請(qǐng)求中提取出來(lái) csrfToken,和保存的 csrfToken 做比較,進(jìn)而判斷出當(dāng)前請(qǐng)求是否合法。

          1.?2021 全球程序員收入報(bào)告出爐,看完我真的拖后腿了。。

          2.?Caffine Cache 在 SpringBoot 中的使用

          3.?著名開(kāi)源項(xiàng)目作者刪庫(kù)跑路,神秘Bug影響超20000個(gè)項(xiàng)目

          4.?18張圖,詳解SpringBoot解析yml全流程

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下在看,加個(gè)星標(biāo),這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

          點(diǎn)“在看”支持小哈呀,謝謝啦??!

          瀏覽 112
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲一区二区 | 日日夜夜三级电影网站 | 国产精品九九九九九九九九九 | 男女wwwwww | 99三级片|