Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲精品亚洲九十七页,久久久网站亚洲第一,91福利电影福利在线观看

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線:

          按鍵精靈教程飛Q短信驗(yàn)證碼范例測(cè)試模板分享

          按鍵精靈教程飛Q短信驗(yàn)證碼范例測(cè)試模板分享

          豬腳本(原飛豬腳本)以按鍵精靈教學(xué)為主,涉及UiBot,Python,Lua等腳本編程語(yǔ)言,教學(xué)包括全自動(dòng)辦公腳本,游戲輔助腳本,引流腳本,網(wǎng)頁(yè)腳本,安卓腳本,IOS腳本,注冊(cè)腳本,點(diǎn)贊腳本,閱讀腳本以及網(wǎng)賺腳本等各個(gè)領(lǐng)域。想制作腳本和學(xué)習(xí)按鍵精靈的朋友可以添加按鍵精靈學(xué)習(xí)交流群:554127455 學(xué)習(xí)路上不再孤單,金豬腳本伴你一同成長(zhǎng).

          答案顯然是有的,今天就給大家介紹下飛Q手機(jī)短信驗(yàn)證平臺(tái)并分享下06大大基于這個(gè)平臺(tái)寫(xiě)的命令庫(kù)與范例調(diào)用模板

          [tr=rgb(154,205,50)]飛Q手機(jī)短信驗(yàn)證碼系統(tǒng)

          關(guān)于該平臺(tái)的介紹具體可以查看:

          飛q短信驗(yàn)證碼官網(wǎng)幫助中心:http://sms.xudan123.com/help.html

          飛q短信驗(yàn)證碼平臺(tái)小視頻介紹:http://www.iqiyi.com/w_19rrp70df9.html?list=19rro6qr82

          [tr=rgb(154,205,50)]模板范例下載

          天縱命令.rar (36.58 K, 下載次數(shù):132)

          該范例有用到表格控件,請(qǐng)使用最新版表格控件版本導(dǎo)入,下載地址:

          【7月24日】按鍵2014.03版新增表格與瀏覽器控件(附例子與源碼),新版本更穩(wěn)定!

          下載解壓后把天縱BASE.qml與天縱VCode.qml這倆個(gè)文件導(dǎo)入到命令庫(kù),然后再導(dǎo)入范例就可以進(jìn)行調(diào)試了

          友情免費(fèi)提供測(cè)試賬號(hào):dd8878dd 密碼:15987530(余額只有2元)

          飛Q獲取驗(yàn)證碼的一般流程

          [tr=rgb(154,205,50)]范例摸板測(cè)試演示

          以搜房網(wǎng)賬號(hào)手動(dòng)模擬注冊(cè)為例

          冊(cè)界面



          手動(dòng)驗(yàn)證獲取短信驗(yàn)證碼


          代碼原文

          pringSecurity-9-實(shí)現(xiàn)通過(guò)手機(jī)短信進(jìn)行認(rèn)證功能

          手機(jī)短信流程分析

          手機(jī)號(hào)登錄的時(shí)候是不需要密碼登錄的,而是通過(guò)短信驗(yàn)證碼實(shí)現(xiàn)免密登錄。具體步驟如下 :

          1. 向手機(jī)發(fā)送驗(yàn)證碼,第三方短信發(fā)送平臺(tái),如阿里云短信
          2. 手機(jī)獲取驗(yàn)證碼后,在表單中輸入驗(yàn)證碼
          3. 使用自定義過(guò)濾器SmsCodeValidateFilter
          4. 短信校驗(yàn)通過(guò)后,使用自定義手機(jī)認(rèn)證過(guò)濾器SmsCodeAuthenticationFilter校驗(yàn)手機(jī)號(hào)碼是否存在
          5. 自定義SmsCodeAuthenticationToken提供給SmsCodeAuthenticationFilter
          6. 自定義SmsCodeAuthenticationProvider提供給AuthenticationManager
          7. 創(chuàng)建針對(duì)手機(jī)號(hào)查詢(xún)用戶(hù)信息的SmsCodeUserDetailsService,提交給SmsCodeAuthenticationProvider
          8. 自定義SmsCodeSecurityConfig配置類(lèi)將上面組件連接起來(lái)
          9. SmsCodeSecurityConfig添加到LearnSrpingSecurity安全配置的過(guò)濾器鏈上

          創(chuàng)建短信發(fā)送接口

          • 定義發(fā)生短信的服務(wù)接口com.security.learn.sms.SmsCodeSend

          代碼如下:

          public interface SmsCodeSend {
              boolean sendSmsCode(String mobile, String code);
          }
          
          • 實(shí)現(xiàn)短信發(fā)生服務(wù)接口com.security.learn.sms.impl.SmsCodeSendImpl代碼如下
          @Slf4j
          public class SmsCodeSendImpl implements SmsCodeSend {
              @Override
              public boolean sendSmsCode(String mobile, String code) {
                  String sendCode = String.format("你好你的驗(yàn)證碼%s,請(qǐng)勿泄露他人。", code);
                  log.info("向手機(jī)號(hào)" + mobile + "發(fā)送的短信為:" + sendCode);
                  return true;
              }
          }
          

          :因?yàn)檫@里是示例所以就沒(méi)有真正的使用第三方發(fā)送短信平臺(tái)。

          • smsCodeSend注入到容器實(shí)現(xiàn)如下
          @Configuration
          public class Myconfig {
              @Bean
              public PasswordEncoder passwordEncoder(){
                  return  new BCryptPasswordEncoder();
              }
              @Bean
              @ConditionalOnMissingBean(SmsCodeSend.class)
              public SmsCodeSend smsCodeSend(){
                  return  new SmsCodeSendImpl();
              }
          }
          

          手機(jī)登錄頁(yè)與發(fā)送短信驗(yàn)證碼

          • 創(chuàng)建SmsController實(shí)現(xiàn)短信發(fā)送驗(yàn)證碼的API,代碼如下:
          @Controller
          public class SmsController {
              public static final String SESSION_KEY = "SESSION_KEY_MOBILE_CODE";
              @RequestMapping("/mobile/page")
              public String toMobilePage(){
                  return "login-mobile";
              }
              @Autowired
              private SmsCodeSend smsCodeSend;
              /**
               *生成手機(jī)驗(yàn)證碼并發(fā)送
               * @param request
               * @return
               */
              @RequestMapping("/code/mobile")
              @ResponseBody
              public String smsCode(HttpServletRequest request){
                  // 1. 生成一個(gè)手機(jī)驗(yàn)證碼
                  String code = RandomStringUtils.randomNumeric(4);
                  request.getSession().setAttribute(SESSION_KEY, code);
                  String mobile = request.getParameter("mobile");
                  smsCodeSend.sendSmsCode(mobile, code);
                  return "200";
              }
          }
          
          • src\main\resources\templates文件夾下添加login-mobile.html靜態(tài)頁(yè)面,具體實(shí)現(xiàn)如下
          <!--suppress ALL-->
          <!DOCTYPE html>
          <html xmlns:th="http://www.thymeleaf.org">
          <head>
              <meta charset="utf-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <title>springboot葵花寶典手機(jī)登錄</title>
              <!-- Tell the browser to be responsive to screen width -->
              <meta name="viewport" content="width=device-width, initial-scale=1">
          </head>
          <body >
          <div >
              <a href="#">springboot葵花寶典手機(jī)登錄</a>  <br>
              <a th:href="@{/login/page}" href="login.html" >
                  <span>使用密碼驗(yàn)證登錄</span>
              </a> <br>
              <form th:action="@{/mobile/form}" action="index.html" method="post">
                  <span>手機(jī)號(hào)碼</span> <input id="mobile" name="mobile" type="text" class="form-control" placeholder="手機(jī)號(hào)碼"><br>
                  <span>驗(yàn)證碼</span> <input type="text" name="smsCode" class="form-control" placeholder="驗(yàn)證碼">  <a id="sendCode" th:attr="code_url=@{/code/mobile?mobile=}" href="#"> 獲取驗(yàn)證碼 </a><br>
                  <!-- 提示信息, 表達(dá)式紅線沒(méi)關(guān)系,忽略它 -->
                  <div th:if="${param.error}">
                      <span th:text="${session.SPRING_SECURITY_LAST_EXCEPTION?.message}" style="color:#ff0000"></span>
                  </div>
                  <span>記住我</span><input type="checkbox" name="remember-me-test" >  <br>
                  <button type="submit" class="btn btn-primary btn-block">登錄</button>
              </form>
          </div>
          <script th:src="@{/plugins/jquery/jquery.min.js}" src="plugins/jquery/jquery.min.js"></script>
          <script>
              // 發(fā)送驗(yàn)證碼
              $("#sendCode").click(function () {
                  var mobile = $('#mobile').val().trim();
                  if(mobile == '') {
                      alert("手機(jī)號(hào)不能為空");
                      return;
                  }
                  var url = $(this).attr("code_url") + mobile;
                  $.get(url, function(data){
                      alert(data === "200" ? "發(fā)送成功": "發(fā)送失敗");
                  });
              });
          </script>
          </body>
          </html>
          
          • LearnSrpingSecurityconfigure(HttpSecurity http)方法中添加手機(jī)免密登錄允許的url
            .and().authorizeRequests()
                          .antMatchers("/login/page","/code/image","/mobile/page","/code/mobile").permitAll()
          

          短信驗(yàn)證碼校驗(yàn)過(guò)濾器 SmsCodeValidateFilter

          短信驗(yàn)證碼的校驗(yàn)過(guò)濾器,實(shí)際上和圖片驗(yàn)證過(guò)濾器原理一致。都都是繼承OncePerRequestFilter實(shí)現(xiàn)一個(gè)Spring環(huán)境下的過(guò)濾器。@Component注解不可少其核心校驗(yàn)規(guī)則如下:

          • 登錄時(shí)候手機(jī)號(hào)碼不可為空
          • 登錄時(shí)手機(jī)輸入碼不可為空
          • 登錄時(shí)輸入的短信驗(yàn)證碼必須和“謎底”中的驗(yàn)證碼一致
          @Component
          public class SmsCodeValidateFilter extends OncePerRequestFilter {
              @Autowired
              MyAuthenticationFailureHandler failureHandler;
              @Override
              protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
                  if (request.getRequestURI().equals("/mobile/form")
                          && request.getMethod().equalsIgnoreCase("post")) {
                      try {
                          validate(request);
                      }catch (AuthenticationException e){
                          failureHandler.onAuthenticationFailure(
                                  request,response,e);
                          return;
                      }
                  }
                  filterChain.doFilter(request,response);
              }
              private void validate(HttpServletRequest request)  {
                  //獲取session中的手機(jī)驗(yàn)證碼
                  HttpSession session = request.getSession();
                  String sessionCode = (String)request.getSession().getAttribute(SmsController.SESSION_KEY);
                  // 獲取用戶(hù)輸入的驗(yàn)證碼
                  String inpuCode = request.getParameter("smsCode");
                  //手機(jī)號(hào)
                  String mobileInRequest = request.getParameter("mobile");
                  if(StringUtils.isEmpty(mobileInRequest)){
                      throw new ValidateCodeException("手機(jī)號(hào)碼不能為空!");
                  }
                  if(StringUtils.isEmpty(inpuCode)){
                      throw new ValidateCodeException("短信驗(yàn)證碼不能為空!");
                  }
                  if(StrUtil.isBlank(sessionCode)){
                      throw new ValidateCodeException("短信驗(yàn)證碼不存在!");
                  }
                  if(!sessionCode.equalsIgnoreCase(inpuCode)){
                      throw new ValidateCodeException("輸入的短信驗(yàn)證碼錯(cuò)誤!");
                  }
                  session.removeAttribute(SmsController.SESSION_KEY);
              }
          }
          

          實(shí)現(xiàn)手機(jī)認(rèn)證SmsCodeAuthenticationFilter過(guò)濾器

          創(chuàng)建com.security.learn.filter.SmsCodeAuthenticationFilter,仿照UsernamePassword AuthenticationFilter進(jìn)行代碼實(shí)現(xiàn),不過(guò)將用戶(hù)名、密碼換成手機(jī)號(hào)進(jìn)行認(rèn)證,短信驗(yàn)證碼在此部分已經(jīng)沒(méi)有用了,因?yàn)槲覀冊(cè)赟msCodeValidateFilter已經(jīng)驗(yàn)證過(guò)了

          public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
              public static final String SPRING_SECURITY_FORM_MOBILE_KEY = "mobile";
              private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY ;    //請(qǐng)求中攜帶手機(jī)號(hào)的參數(shù)名稱(chēng)
              private boolean postOnly = true;    //指定當(dāng)前過(guò)濾器是否只處理POST請(qǐng)求
              public SmsCodeAuthenticationFilter() {
                  //指定當(dāng)前過(guò)濾器處理的請(qǐng)求
                  super(new AntPathRequestMatcher("//mobile/form", "POST"));
              }
              public Authentication attemptAuthentication(
                      HttpServletRequest request,
                      HttpServletResponse response)
                      throws AuthenticationException {
                  if (this.postOnly && !request.getMethod().equals("POST")) {
                      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
                  }
                  //從請(qǐng)求中獲取手機(jī)號(hào)碼
                  String mobile = this.obtainMobile(request);
                  if (mobile == null) {
                      mobile = "";
                  }
                  mobile = mobile.trim();
                  SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile);
                  this.setDetails(request, authRequest);
                  return this.getAuthenticationManager().authenticate(authRequest);
              }
              /**
               * 從從請(qǐng)求中獲取手機(jī)號(hào)碼
               * @param request
               * @return
               */
              protected String obtainMobile(HttpServletRequest request) {
                  return request.getParameter(this.mobileParameter);
              }
              /**
               * 將請(qǐng)求中的Sessionid和host主句ip放到SmsCodeAuthenticationToken中
               * @param request
               * @param authRequest
               */
              protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authRequest) {
                  authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
              }
              public void setMobileParameter(String mobileParameter) {
                  Assert.hasText(mobileParameter, "Username parameter must not be empty or null");
                  this.mobileParameter = mobileParameter;
              }
              public void setPostOnly(boolean postOnly) {
                  this.postOnly = postOnly;
              }
              public final String getMobileParameter() {
                  return this.mobileParameter;
              }
          }
          

          封裝手機(jī)認(rèn)證Token SmsCodeAuthenticationToken

          創(chuàng)建com.security.learn.filter.SmsCodeAuthenticationToken,仿照UsernamePasswordAuthenticationToken進(jìn)行代碼實(shí)現(xiàn)

          public class SmsCodeAuthenticationToken  extends AbstractAuthenticationToken {
              private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
              //存放認(rèn)證信息,認(rèn)證之前存放手機(jī)號(hào),認(rèn)證之后存放登錄的用戶(hù)
              private final Object principal;
              /**
               * 開(kāi)始認(rèn)證時(shí),SmsCodeAuthenticationToken 接收的是手機(jī)號(hào)碼, 并且 標(biāo)識(shí)未認(rèn)證
               * @param mobile
               */
              public SmsCodeAuthenticationToken(String mobile) {
                  super(null);
                  this.principal = mobile;
                  this.setAuthenticated(false);
              }
              /**
               *  當(dāng)認(rèn)證通過(guò)后,會(huì)重新創(chuàng)建一個(gè)新的SmsCodeAuthenticationToken,來(lái)標(biāo)識(shí)它已經(jīng)認(rèn)證通過(guò),
               * @param principal 用戶(hù)信息
               * @param authorities 用戶(hù)權(quán)限
               */
              public SmsCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
                  super(authorities);
                  this.principal = principal;
                  super.setAuthenticated(true);//表示認(rèn)證通過(guò)
              }
              /**
               * 在父類(lèi)中是一個(gè)抽象方法,所以要實(shí)現(xiàn), 但是它是密碼,而當(dāng)前不需要,則直接返回null
               * @return
               */
              public Object getCredentials() {
                  return null;
              }
              /**
               * 手機(jī)號(hào)獲取
               * @return
               */
              public Object getPrincipal() {
                  return this.principal;
              }
              public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
                  if (isAuthenticated) {
                      throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
                  }
                  super.setAuthenticated(false);
              }
              public void eraseCredentials() {
                  super.eraseCredentials();
              }
          }
          

          手機(jī)認(rèn)證提供者 SmsCodeAuthenticationProvider

          創(chuàng)建com.security.learn.filter.SmsCodeAuthenticationProvider,提供給底層的ProviderManager代碼實(shí)現(xiàn)如下

          public class SmsCodeAuthenticationProvider implements AuthenticationProvider {
              @Autowired
              @Qualifier("smsCodeUserDetailsService")
              private UserDetailsService userDetailsService;
              public UserDetailsService getUserDetailsService() {
                  return userDetailsService;
              }
              public void setUserDetailsService(UserDetailsService userDetailsService) {
                  this.userDetailsService = userDetailsService;
              }
              /**
               * 處理認(rèn)證:
               * 1. 通過(guò) 手機(jī)號(hào) 去數(shù)據(jù)庫(kù)查詢(xún)用戶(hù)信息(UserDeatilsService)
               * 2. 再重新構(gòu)建認(rèn)證信息
               * @param authentication
               * @return
               * @throws AuthenticationException
               */
              @Override
              public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                  //利用UserDetailsService獲取用戶(hù)信息,拿到用戶(hù)信息后重新組裝一個(gè)已認(rèn)證的Authentication
                  SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken)authentication;
                  UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());  //根據(jù)手機(jī)號(hào)碼拿到用戶(hù)信息
                  if(user == null){
                      throw new AuthenticationServiceException("無(wú)法獲取用戶(hù)信息");
                  }
                  SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user,user.getAuthorities());
                  authenticationResult.setDetails(authenticationToken.getDetails());
                  return authenticationResult;
              }
              /**
               * AuthenticationManager挑選一個(gè)AuthenticationProvider
               * 來(lái)處理傳入進(jìn)來(lái)的Token就是根據(jù)supports方法來(lái)判斷的
               * @param aClass
               * @return
               */
              @Override
              public boolean supports(Class<?> aClass) {
                  return SmsCodeAuthenticationToken.class.isAssignableFrom(aClass);
              }
          }
          

          手機(jī)號(hào)獲取用戶(hù)信息 SmsCodeUserDetailsService

          創(chuàng)建com.security.learn.impl.SmsCodeUserDetailsService類(lèi),不要注入PasswordEncoder

          @Slf4j
          @Component("smsCodeUserDetailsService")
          public class SmsCodeUserDetailsService implements UserDetailsService {
              @Override
              public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
                  log.info("請(qǐng)求的手機(jī)號(hào)是:" + mobile);
                  return new User(mobile, "", true, true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));
              }
          }
          

          因?yàn)闇y(cè)試就沒(méi)有去數(shù)據(jù)庫(kù)中獲取手機(jī)號(hào)

          自定義管理認(rèn)證配置 SmsCodeSecurityConfig

          最后我們將以上實(shí)現(xiàn)進(jìn)行組裝,并將以上接口實(shí)現(xiàn)以配置的方式告知Spring Security。因?yàn)榕渲么a比較多,所以我們單獨(dú)抽取一個(gè)關(guān)于短信驗(yàn)證碼的配置類(lèi)SmsCodeSecurityConfig,繼承自SecurityConfigurerAdapter。將上面定義的組件綁定起來(lái),添加到容器中:

          注意添加@Component注解

          @Component
          public class SmsCodeSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
              
              @Autowired
              @Qualifier("smsCodeUserDetailsService")
              private SmsCodeUserDetailsService smsCodeUserDetailsService;
              @Resource
              private SmsCodeValidateFilter  smsCodeValidateFilter;
              @Override
              public void configure(HttpSecurity http) throws Exception {
                  //創(chuàng)建手機(jī)校驗(yàn)過(guò)濾器實(shí)例
                  SmsCodeAuthenticationFilter smsCodeAuthenticationFilter = new SmsCodeAuthenticationFilter();
                  //接收 AuthenticationManager 認(rèn)證管理器
                  smsCodeAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
                  //處理成功handler
                  //smsCodeAuthenticationFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
                  //處理失敗handler
                  //smsCodeAuthenticationFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
                  smsCodeAuthenticationFilter.setRememberMeServices(http.getSharedObject(RememberMeServices.class));
                  // 獲取驗(yàn)證碼提供者
                  SmsCodeAuthenticationProvider smsCodeAuthenticationProvider = new SmsCodeAuthenticationProvider();
                  smsCodeAuthenticationProvider.setUserDetailsService(smsCodeUserDetailsService);
                  //在用戶(hù)密碼過(guò)濾器前面加入短信驗(yàn)證碼校驗(yàn)過(guò)濾器
                  http.addFilterBefore(smsCodeValidateFilter, UsernamePasswordAuthenticationFilter.class);
                  //在用戶(hù)密碼過(guò)濾器后面加入短信驗(yàn)證碼認(rèn)證授權(quán)過(guò)濾器
                  http.authenticationProvider(smsCodeAuthenticationProvider)
                          .addFilterAfter(smsCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
              }
          }
          

          綁定到安全配置 LearnSrpingSecurity

          1. . 向 LearnSrpingSecurity中注入 SmsCodeValidateFilter和 SmsCodeSecurityConfig實(shí)例
          2. 將 SmsCodeValidateFilter實(shí)例添加到 UsernamePasswordAuthenticationFilter 前面
            http.csrf().disable() //禁用跨站csrf攻擊防御,后面的章節(jié)會(huì)專(zhuān)門(mén)講解
                          //.addFilterBefore(codeValidateFilter, UsernamePasswordAuthenticationFilter.class)
                          .addFilterBefore(smsCodeValidateFilter, UsernamePasswordAuthenticationFilter.class)
          
          1. 在 LearnSrpingSecurity#confifigure(HttpSecurity http) 方法體最后調(diào)用 apply 添加 SmsCodeSecurityConfig
                          .and()
                          .apply(smsCodeSecurityConfig)
          

          具體實(shí)現(xiàn)如圖

          實(shí)現(xiàn)手機(jī)登錄RememberMe功能

          實(shí)現(xiàn)分析

          1. UsernamePasswordAuthenticationFilter過(guò)濾器中有一個(gè)RememberMeServices引用,它的父類(lèi)AbstractAuthenticationProcessingFilter,提供提供的 setRememberMeServices方法。
          2. 而在實(shí)現(xiàn)手機(jī)短信驗(yàn)證碼登錄時(shí),我們自定了一個(gè) MobileAuthenticationFilter 也一樣的繼承了AbstractAuthenticationProcessingFilter 它,我們只要向其 setRememberMeServices 方法手動(dòng)注入一 個(gè) RememberMeServices 實(shí)例即可。

          代碼實(shí)現(xiàn)

          1. com.security.learn.config.SmsCodeSecurityConfig中向SmsCodeAuthenticationFilter中注入RememberMeServices實(shí)例
           smsCodeAuthenticationFilter.setRememberMeServices(http.getSharedObject(RememberMeServices.class));
          

          • 檢查 記住我 的 input 標(biāo)簽的 name="remember-me-test"
          <span>記住我</span><input type="checkbox" name="remember-me-test" >  <br>
          
          • rememberMeParameter設(shè)置from表單“自動(dòng)登錄”勾選框的參數(shù)名稱(chēng)。如果這里改了,from表單中checkbox的name屬性要對(duì)應(yīng)的更改。如果不設(shè)置默認(rèn)是remember-me。
          • rememberMeCookieName設(shè)置了保存在瀏覽器端的cookie的名稱(chēng),如果不設(shè)置默認(rèn)也是remember-me。如下圖中查看瀏覽器的cookie。

          測(cè)試

          重啟項(xiàng)目,訪問(wèn) http://localhost:8888/mobile/page輸入手機(jī)號(hào)與驗(yàn)證碼, 勾選 記住我 , 點(diǎn)擊登錄

          查看數(shù)據(jù)庫(kù)中中 persistent_logins 表的記錄

          關(guān)閉瀏覽器, 再重新打開(kāi)瀏覽器訪問(wèn)http://localhost:8888 , 發(fā)現(xiàn)會(huì)跳轉(zhuǎn)回用戶(hù)名密碼登錄頁(yè),而正常應(yīng)該勾選了 記住我 , 這一步應(yīng)該是可以正常訪問(wèn)的.

          錯(cuò)誤原因

          數(shù)據(jù)庫(kù)中 username 為 手機(jī)號(hào) 1333383XXXX, 當(dāng)你訪問(wèn)http://localhost:8888默認(rèn)RememberMeServices 是調(diào)

          用 CustomUserDetailsService 通過(guò)用戶(hù)名查詢(xún), 而 當(dāng)前在 CustomUserDetailsService 判斷了用戶(hù)名為 admin才通

          過(guò)認(rèn)證, 而此時(shí)傳入的用戶(hù)名是 1333383XXXX, 所以查詢(xún)不到 1333383XXXX用戶(hù)數(shù)據(jù)

          錯(cuò)誤解決方式

          數(shù)據(jù)庫(kù)中的 persistent_logins 表為什么存儲(chǔ)的是手機(jī)號(hào)?原因是當(dāng)前在 SmsCodeUserDetailsService中返回的 User 對(duì)象中的 username 屬性設(shè)置的是手機(jī)號(hào) mobile,而應(yīng)該設(shè)置這個(gè)手機(jī)號(hào)所對(duì)應(yīng)的那個(gè)用戶(hù)名. 比如當(dāng)前username 的值

          @Slf4j
          @Component("smsCodeUserDetailsService")
          public class SmsCodeUserDetailsService implements UserDetailsService {
              @Override
              public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
                  log.info("請(qǐng)求的手機(jī)號(hào)是:" + mobile);
                  return new User("admin", "", true, true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));
              }
          }
          

          :我們這里實(shí)際上是寫(xiě)為固定admin了實(shí)際上需要通過(guò)數(shù)據(jù)庫(kù)根據(jù)手機(jī)號(hào)獲取用戶(hù)信息。

          關(guān)閉瀏覽再打開(kāi)訪問(wèn)http://localhost:8888就無(wú)需手動(dòng)登錄認(rèn)證了。因?yàn)槟J(rèn)采用的 CustomUserDetailsService 查詢(xún)可查詢(xún)到用戶(hù)名為 admin 的信息,即認(rèn)證通過(guò)

          如果您覺(jué)得本文不錯(cuò),歡迎關(guān)注,點(diǎn)贊,收藏支持,您的關(guān)注是我堅(jiān)持的動(dòng)力!

          原創(chuàng)不易,轉(zhuǎn)載請(qǐng)注明出處,感謝支持!如果本文對(duì)您有用,歡迎轉(zhuǎn)發(fā)分享!


          主站蜘蛛池模板: 国产精品香蕉在线一区| 久久er99热精品一区二区| 国产精品视频一区国模私拍| 少妇人妻精品一区二区三区| 久久亚洲日韩精品一区二区三区| 变态拳头交视频一区二区| 久久久久女教师免费一区| 插我一区二区在线观看| 国产无线乱码一区二三区| 亚洲一区电影在线观看| 国产精品视频一区| 日韩人妻无码一区二区三区综合部 | 中文字幕在线精品视频入口一区| 国产成人精品一区在线| 午夜福利一区二区三区高清视频| 在线精品视频一区二区| 人妻无码一区二区三区四区| 国产一区二区三区久久| 亚洲乱色熟女一区二区三区蜜臀| 精品一区二区三区电影| 国产精品毛片一区二区三区| 亚洲丰满熟女一区二区哦| 午夜福利国产一区二区| 人妻体体内射精一区二区| 国产精品熟女视频一区二区| 久久国产免费一区| 国产伦精品一区二区三区视频小说 | 精品在线一区二区| 久久久综合亚洲色一区二区三区| 久热国产精品视频一区二区三区 | 国产一区二区三区乱码| 成人一区二区三区视频在线观看| 亚洲一区二区三区香蕉| 日本精品视频一区二区三区| 国产一区二区女内射| 精品一区二区三区影院在线午夜| 中文字幕一区二区三区精彩视频| 精品一区二区三区无码免费直播| 精品国产乱子伦一区二区三区 | 日韩人妻精品无码一区二区三区 | 亚洲日本一区二区|