精华内容
下载资源
问答
  • 校验验证码的Session是否为空或者校验用户输入的验证码是否合法,构造安全表单的关键就是永远不要相信用户的输入
  • 知码小编记不得在哪儿看见过,大家在一般情况下,对于验证码校验都很容易写成下面这样:

        知码小编记不得在哪儿看见过,大家在一般情况下,对于验证码的校验都很容易写成下面这样:
     

    展开全文
  • 大家都知道每个网站的安全校验机制都是网站安全的重要组成部分,包括密码、短信验证码、二维码验证等验证方式,除此之外,我们登陆很多网站都能了解到用户登录是会有验证码校验功能的。 在此之前,TSINGSEE青犀视频...

    大家都知道每个网站的安全校验机制都是网站安全的重要组成部分,包括密码、短信验证码、二维码验证等验证方式,除此之外,我们登陆很多网站都能了解到用户登录是会有验证码校验功能的。

    在此之前,TSINGSEE青犀视频开发的EasyNVR、EasyGBS等平台已经实现了验证码的校验功能,为了让TSINGSEE青犀视频平台实现全面安全登陆验证,我们在EasyRTC里也添加了该功能。本文和大家分享下我们的实现过程。

    17.png

    我们使用的方式是首先通过接口获取到captchaId,拿到ID后通过拼接location.origin来获取验证码图片,将照片渲染到页面。用户在输入账号、密码以及验证码后,通过login接口将之前的captchaId一起发送给后端,由后端进行匹配,然后将结果返回给前端。

    后端匹配机制的参考代码如下:

        // 获取验证码照片
        getCaptchaId() {
          getCaptchaId().then((res) => {
            this.loginForm.captcha_id = res.msg.id;
            this.CaptchaUrl = `${location.origin}/v1/auth/captcha/${res.msg.id}.png`;
          });
        },
    

    前端反应的参考代码如下:

    if (valid) {
              let params = {
                loginName: this.loginForm.name,
                password:smCrypto.sm3(this.loginForm.password),
                captchaId:this.loginForm.captcha_id,
                captchaValue: this.loginForm.captcha_code,
              };
              login(params)
                .then((res) => {
                  this.$message({
                    message: "登录成功",
                    type: "success",
                  });
    

    EasyRTC对于细节的优化还会继续,如果大家有兴趣,可以关注我们的博客,我们将会不定期分享我们的开发记录以及解决方案。EasyRTC作为网页音视频通话会议系统,具备一对多的视频会议通话功能,满足语音视频社交、在线教育和培训等需求,支持试用,如果大家想了解更多,欢迎联系我们。

    813619c589974b3bd00f65a7a4991d06.png

    展开全文
  • 在说Android中的短信验证码这个知识点前,我们首先来了解下聚合数据 聚合数据介绍 聚合数据是一家国内最大的基础数据API提供商,专业从事互联网数据服务。免费提供从天气查询、空气质量、地图坐标到金融基金、电商...

    在说Android中的短信验证码这个知识点前,我们首先来了解下聚合数据

    聚合数据介绍

    聚合数据是一家国内最大的基础数据API提供商,专业从事互联网数据服务。免费提供从天气查询、空气质量、地图坐标到金融基金、电商比价、违章查询等各个领域的安全、稳定和高效的数据。开发者可以免费试用聚合数据API进行移动APP的快速开发,免除数据收集、维护等环节,大大降低开发周期及成本。因此我们可以采用聚合数据给我提供好的一套东西来进行短信验证码的功能的添加。

    首先我们要做准备工作,使用聚合数据主要分为以下步骤:

    第一步,注册聚合数据

    进入聚合数据官网(https://www.juhe.cn/)注册一个账号,完成注册后进入,”个人中心”——>“我的数据”点击申请数据如下图所示:

    第二步,申请Appkey

    申请后你会得到一个Appkey,此Appkey非常重要。

    第三步,下载SDK

    下载地址:https://www.juhe.cn/juhesdk

    第四步,创建工程,配置环境

    1.创建一个工程把我们下载的SDK里libs下的“armeabi文件”和”smscaptcha_v_1_4.jar”复制到我们工程的libs目录下

    2.在AndroidManifest中添加开发密钥、所需权限等信息

     (1)在application中添加开发密钥

    1. <meta-data      
    2.       android:name=“JUHE_KEY”      
    3.       android:value=“开发者 key” />    
    <meta-data    
          android:name="JUHE_KEY"    
          android:value="开发者 key" />  
    (2)添加所需权限
    1. <uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE” />      
    2. <uses-permission android:name=”android.permission.INTERNET” />      
    3. <uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />      
    4. <uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION ” />      
    5. <uses-permission android:name=”android.permission.READ_FINE_LOCATION” />    
    6. <uses-permission android:name=”android.permission.READ_PHONE_STATE” />    
    7. <uses-permission android:name=”android.permission.READ_CONTACTS” />    
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    
    <uses-permission android:name="android.permission.INTERNET" />    
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />    
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION " />    
    <uses-permission android:name="android.permission.READ_FINE_LOCATION" />  
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
    <uses-permission android:name="android.permission.READ_CONTACTS" />  

    (3)在应用程序创建时初始化 SDK引用的Context全局变量

    在这一步我们有两种方法

    第一种在Activity中配置

    1. public class MainActivity extends Activity {      
    2.     @Override      
    3.     protected void onCreate(Bundle savedInstanceState) {      
    4.         super.onCreate(savedInstanceState);       
    5.         //在使用SDK各组件之前初始化context信息,传入ApplicationContext      
    6.         //注意该方法要再setContentView方法之前实现      
    7.     /**   
    8.     * 初始化方法  
    9.     * @param context  
    10.     * @needFriends 是否需要好友功能  
    11.     */     
    12.         CommonFun.initialize(getApplicationContext(),true);      
    13.         setContentView(R.layout.activity_main);      
    14.     }      
    15. }    
    public class MainActivity extends Activity {    
        @Override    
        protected void onCreate(Bundle savedInstanceState) {    
            super.onCreate(savedInstanceState);     
            //在使用SDK各组件之前初始化context信息,传入ApplicationContext    
            //注意该方法要再setContentView方法之前实现    
        /**  
        * 初始化方法 
        * @param context 
        * @needFriends 是否需要好友功能 
        */   
            CommonFun.initialize(getApplicationContext(),true);    
            setContentView(R.layout.activity_main);    
        }    
    }  

    下面这个注意是聚合数据文档给我们的建议,它建议我们把这个初始化工作放在Application中,因为程序运行首先会运行Application中的方法

    注意:SDK各功能组件使用之前都需要调用CommonFun.initialize(getApplicationContext(),true);,因此我们建议该方法放在Application的初始化方法中

    所以我们就按它建议的方法,而不采用第一种方法这样我们需要创建一个Applicaiton类MyApplication如下

    1. package com.example.android.sms;    
    2.     
    3. import com.thinkland.sdk.util.CommonFun;    
    4.     
    5. import android.app.Application;    
    6.     
    7. public class MyApplication extends Application {    
    8.     
    9.     @Override    
    10.     public void onCreate() {    
    11.         super.onCreate();    
    12.         CommonFun.initialize(getApplicationContext(), false);     
    13.     }    
    14. }    
    package com.example.android.sms;  
    
    import com.thinkland.sdk.util.CommonFun;  
    
    import android.app.Application;  
    
    public class MyApplication extends Application {  
    
        @Override  
        public void onCreate() {  
            super.onCreate();  
            CommonFun.initialize(getApplicationContext(), false);   
        }  
    }  

    声明好Application后不要忘了在清单文件中配置

     

    好了环境已经配置好了,我们来验证一下看看我们是否能收到短信

    MainActivity的代码如下

    1. package com.example.android.sms;    
    2.     
    3. import com.thinkland.sdk.sms.SMSCaptcha;    
    4. import com.thinkland.sdk.util.BaseData;    
    5. import com.thinkland.sdk.util.CommonFun;    
    6.     
    7. import android.os.Bundle;    
    8. import android.app.Activity;    
    9. import android.util.Log;    
    10. import android.view.Menu;    
    11. import android.widget.Toast;    
    12.     
    13. public class MainActivity extends Activity {    
    14.     
    15.     protected static final String TAG =“MainActivity”;    
    16.     
    17.     @Override    
    18.     protected void onCreate(Bundle savedInstanceState) {    
    19.         super.onCreate(savedInstanceState);    
    20.         
    21.         setContentView(R.layout.activity_main);    
    22.         //初始化 SMSCaptcha对象在这个对象中有给我们发送短信验证码的方法    
    23.         SMSCaptcha smsCaptcha=SMSCaptcha.getInstance();    
    24.         //调用发送短信验证码的方法,在其中有一个回调    
    25.             
    26.         /**  
    27.           phone 手机号码  
    28.           callBack  返回结果回调方法.  
    29.          */    
    30.         smsCaptcha.sendCaptcha(”此处输入你的手机号”,new BaseData.ResultCallBack() {    
    31.                 
    32.             @Override    
    33.             public void onResult(int code, String reason, String result) {    
    34.                     
    35.                    /*  
    36.                     code:返回码:  
    37.                     服务器: 0 成功; 1 错误;  
    38.                     本地: -2 本地网络异常; -3 服务器网络异常;-4 解析错误;-5初始化异常  
    39.                     reason:返回信息 成功或错误原因.  
    40.                     result:返回结果,JSON格式.错误或者无返回值时为空.*/    
    41.                     
    42.                 if(code==0){    
    43.                     Log.i(TAG,”code=”+code);    
    44.                     Log.i(TAG,”reason=”+reason);    
    45.                     Log.i(TAG,”result=”+result);    
    46.                 }    
    47.             }    
    48.         });    
    49.     }    
    50. }    
    package com.example.android.sms;  
    
    import com.thinkland.sdk.sms.SMSCaptcha;  
    import com.thinkland.sdk.util.BaseData;  
    import com.thinkland.sdk.util.CommonFun;  
    
    import android.os.Bundle;  
    import android.app.Activity;  
    import android.util.Log;  
    import android.view.Menu;  
    import android.widget.Toast;  
    
    public class MainActivity extends Activity {  
    
        protected static final String TAG ="MainActivity";  
    
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
    
            setContentView(R.layout.activity_main);  
            //初始化 SMSCaptcha对象在这个对象中有给我们发送短信验证码的方法  
            SMSCaptcha smsCaptcha=SMSCaptcha.getInstance();  
            //调用发送短信验证码的方法,在其中有一个回调  
    
            /** 
              phone 手机号码 
              callBack  返回结果回调方法. 
             */  
            smsCaptcha.sendCaptcha("此处输入你的手机号",new BaseData.ResultCallBack() {  
    
                @Override  
                public void onResult(int code, String reason, String result) {  
    
                       /* 
                        code:返回码: 
                        服务器: 0 成功; 1 错误; 
                        本地: -2 本地网络异常; -3 服务器网络异常;-4 解析错误;-5初始化异常 
                        reason:返回信息 成功或错误原因. 
                        result:返回结果,JSON格式.错误或者无返回值时为空.*/  
    
                    if(code==0){  
                        Log.i(TAG,"code="+code);  
                        Log.i(TAG,"reason="+reason);  
                        Log.i(TAG,"result="+result);  
                    }  
                }  
            });  
        }  
    }  

    返回结果如下:

    第五步:完整的功能的实现,以及界面UI的实现

    首先我们来看下界面第一个界面

    我们在这个界面输入手机号,及短信的目的地,点击下一步后会弹出一个Dialog

    点击确定后会调用会调用聚合数据给我们提供的sendCaptcha方法

    1.     /*点击确定后调用sendCaptcha方法向服务器提交手机号码  
    2.                   code(返回码):   
    3.                   服务器:0 成功,1 错误;   
    4.                   本  地:-2 本地网络异常,-3 服务器网络异常,-4 解析错误,-5 初始化异常。   
    5.                   reason(返回信息):成功或错误的原因。   
    6.                   result(返回结果):JSON格式,错误或者无返回值时为空。   
    7.                 */     
    8. smsCaptcha.sendCaptcha(phone,new ResultCallBack() {    
    9.                         
    10. @Override    
    11. public void onResult(int code, String reason, String result) {    
    12. closeDialog();    
    13. if(code==0){    
    14. afterCapterRequested();    
    15. }                           
    16.   }    
    17.     
    18. );    
        /*点击确定后调用sendCaptcha方法向服务器提交手机号码 
                      code(返回码):  
                      服务器:0 成功,1 错误;  
                      本  地:-2 本地网络异常,-3 服务器网络异常,-4 解析错误,-5 初始化异常。  
                      reason(返回信息):成功或错误的原因。  
                      result(返回结果):JSON格式,错误或者无返回值时为空。  
                    */   
    smsCaptcha.sendCaptcha(phone,new ResultCallBack() {  
    
    @Override  
    public void onResult(int code, String reason, String result) {  
    closeDialog();  
    if(code==0){  
    afterCapterRequested();  
    }                         
      }  
    
    );  
    当返回的code==0时说明短信验证码发送成功,我们需要进行界面的跳转,代码如下
    1. //当code=0成功时,跳转到输入验证码的Activity    
    2.     private void afterCapterRequested() {    
    3.         String phone=etPhoneNumber.getText().toString().trim().replaceAll(”\\ss*”,     
    4.                 ”“);    
    5.         String code=tvCountryNumber.getText().toString().trim();    
    6.         String fomatedPhone=code+” ”+splitPhoneNum(phone);    
    7.             
    8.         Toast.makeText(this,“成功”,Toast.LENGTH_SHORT).show();    
    9.         Intent intent=new Intent();    
    10.         intent.setClass(RegistActivity.this,CaptchaActivity.class);    
    11.         //把手机号码和格式化的手机号码传过去    
    12.         intent.putExtra(”formatedPhone”,fomatedPhone);    
    13.         intent.putExtra(”phone”,phone);    
    14.         startActivity(intent);    
    15.     }    
    16.         
    17.     //格式化手机号码的方法,格式化后的形式:+86 131 4118 2951    
    18.     private String splitPhoneNum(String phone) {    
    19.             
    20.         StringBuilder builder=new StringBuilder(phone);    
    21.         builder.reverse();    
    22.         for(int i=4,len=builder.length();i<len;i+=5){    
    23.             builder.insert(i,’ ’);    
    24.         }    
    25.         builder.reverse();    
    26.         return builder.toString();    
    27.     }    
    //当code=0成功时,跳转到输入验证码的Activity  
        private void afterCapterRequested() {  
            String phone=etPhoneNumber.getText().toString().trim().replaceAll("\\ss*",   
                    "");  
            String code=tvCountryNumber.getText().toString().trim();  
            String fomatedPhone=code+" "+splitPhoneNum(phone);  
    
            Toast.makeText(this,"成功",Toast.LENGTH_SHORT).show();  
            Intent intent=new Intent();  
            intent.setClass(RegistActivity.this,CaptchaActivity.class);  
            //把手机号码和格式化的手机号码传过去  
            intent.putExtra("formatedPhone",fomatedPhone);  
            intent.putExtra("phone",phone);  
            startActivity(intent);  
        }  
    
        //格式化手机号码的方法,格式化后的形式:+86 131 4118 2951  
        private String splitPhoneNum(String phone) {  
    
            StringBuilder builder=new StringBuilder(phone);  
            builder.reverse();  
            for(int i=4,len=builder.length();i<len;i+=5){  
                builder.insert(i,' ');  
            }  
            builder.reverse();  
            return builder.toString();  
        }  

    跳转的界面的布局如下

    在这个界面我们需要输入短信验证码,输入短信验证码后点击下一步时会调用聚合数据的commitCaptcha这个方法,比对数据的方法,

    1. smsCaptcha.commitCaptcha(phoneNumbber,verfiyCode,new ResultCallBack() {    
    2.         /*   
    3.                     code:返回码:   
    4.                     服务器: 0 成功; 1 错误;   
    5.                     本地: -2 本地网络异常; -3 服务器网络异常;-4 解析错误;-5初始化异常   
    6.                     reason:返回信息 成功或错误原因.   
    7.                     result:返回结果,JSON格式.错误或者无返回值时为空.*/     
    8.         @Override    
    9.         public void onResult(int code,String reason,String result) {    
    10.         if(code==0){    
    11.         Log.i(TAG,code+”“);    
    12.         Log.i(TAG,reason);    
    13.         Log.i(TAG,result);    
    14.         Toast.makeText(CaptchaActivity.this,“您输入的验证码正确”,Toast.LENGTH_SHORT).show();    
    15.         CaptchaActivity.this.finish();    
    16.         }else{    
    17.         Toast.makeText(CaptchaActivity.this,“您输入的验证码不正确”,Toast.LENGTH_SHORT).show();    
    18.                 }    
    19.             }    
    20.         });    
    smsCaptcha.commitCaptcha(phoneNumbber,verfiyCode,new ResultCallBack() {  
            /*  
                        code:返回码:  
                        服务器: 0 成功; 1 错误;  
                        本地: -2 本地网络异常; -3 服务器网络异常;-4 解析错误;-5初始化异常  
                        reason:返回信息 成功或错误原因.  
                        result:返回结果,JSON格式.错误或者无返回值时为空.*/   
            @Override  
            public void onResult(int code,String reason,String result) {  
            if(code==0){  
            Log.i(TAG,code+"");  
            Log.i(TAG,reason);  
            Log.i(TAG,result);  
            Toast.makeText(CaptchaActivity.this,"您输入的验证码正确",Toast.LENGTH_SHORT).show();  
            CaptchaActivity.this.finish();  
            }else{  
            Toast.makeText(CaptchaActivity.this,"您输入的验证码不正确",Toast.LENGTH_SHORT).show();  
                    }  
                }  
            });  
    我们可以看到这个方法所需的参数是①手机号码②手机验证码,我们调用此方法后聚合数据的服务器会进行判断,此验证码是否是刚才发送给这个手机号的验证码,验证后给我返回结果,我们根据返回的结果就可以进行相应的操作。
    在上面的界面中我们发现有一个倒计时的功能,我在这里说一下思路,当然这个倒计时方法有很多。在这个Demo中倒计时是放在一个tvCountDown的一个textView中,首先
    1. //R.string.receiveMessgeCountDown的内容为:<Data>接收短信大约需要<font color=#209526>%s</font>秒</Data>    
    2. //这句话就是用time把 html里的%号替换掉    
    3. String unReceive=getResources().getString(R.string. receiveMessgeCountDown,time );    
    4. //把用html格式化的字符串设置给倒计时的文本框    
    5. tvCountDown.setText(Html.fromHtml(unReceive));    
    //R.string.receiveMessgeCountDown的内容为:<Data>接收短信大约需要<font color=#209526>%s</font>秒</Data>  
    //这句话就是用time把 html里的%号替换掉  
    String unReceive=getResources().getString(R.string. receiveMessgeCountDown,time );  
    //把用html格式化的字符串设置给倒计时的文本框  
    tvCountDown.setText(Html.fromHtml(unReceive));  
    这样我们可以把html格式化的文本填充到tvCountDown中。接下来就是倒计时的方法了
    1. private final int RETRY_INTERVAL =60;    
    2. private int time=RETRY_INTERVAL;    
    3.      //倒计时方法    
    4.      private void countDown() {    
    5.             new Thread( new Runnable() {    
    6.                     
    7.                  @Override    
    8.                  public void run() {    
    9.                  while( time–>0){    
    10.                //减一后的time把<Data>接收短信大约需要<font color=#209526>%s</font>秒</Data>中的%号替换掉    
    11.                 String countDownTime=CaptchaActivity.this .getResources().getString(R.string. receiveMessgeCountDown,time );    
    12.               //在主线程上更新tvCountDown    
    13.               upDateTvCountDown(countDownTime);    
    14.               try {    
    15.                  Thread. sleep(1000);    
    16.                   } catch (InterruptedException e) {    
    17.                       e.printStackTrace();    
    18.                      }    
    19.                  }       
    20.                 String countDownTime=CaptchaActivity.this .getResources().getString(R.string. unreceiveMessage, time);    
    21.                upDateTvCountDown(countDownTime);    
    22.                time = RETRY_INTERVAL;    
    23.            }    
    24.      }).start();    
    25. }    
    26. //在主线程上更新tvCountDown    
    27. private void upDateTvCountDown(final String countDownTime) {    
    28.            runOnUiThread( new Runnable() {    
    29.                  @Override    
    30.                  public void run() {    
    31.                   tvCountDown.setText(Html. fromHtml(countDownTime));    
    32.                   tvCountDown.setEnabled( false);    
    33.                 }    
    34.            });    
    35.      }    
    private final int RETRY_INTERVAL =60;  
    private int time=RETRY_INTERVAL;  
         //倒计时方法  
         private void countDown() {  
                new Thread( new Runnable() {  
    
                     @Override  
                     public void run() {  
                     while( time-->0){  
                   //减一后的time把<Data>接收短信大约需要<font color=#209526>%s</font>秒</Data>中的%号替换掉  
                    String countDownTime=CaptchaActivity.this .getResources().getString(R.string. receiveMessgeCountDown,time );  
                  //在主线程上更新tvCountDown  
                  upDateTvCountDown(countDownTime);  
                  try {  
                     Thread. sleep(1000);  
                      } catch (InterruptedException e) {  
                          e.printStackTrace();  
                         }  
                     }     
                    String countDownTime=CaptchaActivity.this .getResources().getString(R.string. unreceiveMessage, time);  
                   upDateTvCountDown(countDownTime);  
                   time = RETRY_INTERVAL;  
               }  
         }).start();  
    }  
    //在主线程上更新tvCountDown  
    private void upDateTvCountDown(final String countDownTime) {  
               runOnUiThread( new Runnable() {  
                     @Override  
                     public void run() {  
                      tvCountDown.setText(Html. fromHtml(countDownTime));  
                      tvCountDown.setEnabled( false);  
                    }  
               });  
         }  
    总结:其实使用聚合数据的短信验证码功能,主要就两个方法,一个是获取验证码的方法sendCaptcha,一个是提交验证码进行验证的方法commitCaptcha。我们在此基础上,可以根据需求对界面进行更改。以上就是对短信验证码的主要逻辑进行的介绍。

    转载来源:http://blog.csdn.net/ishxiao/article/details/52710870

    展开全文
  • 为了安全考虑,还需要加上验证码。 一、验证码的发展史 验证码这个词最早是在2002年由卡内基梅隆大学的路易斯·冯·安、Manuel Blum、Nicholas J.Hopper以及IBM的John Langford所提出。卡...

    上一篇教程《SSM整合之企业级后台管理系统(9) - 登录页面和登录跳转实现》中已经和大家一起学习了使用用户名和密码进行登录,当然,登录的时候只用用户名和密码是不够滴!为了安全考虑,还需要加上验证码。

    一、验证码的发展史

    验证码这个词最早是在2002年由卡内基梅隆大学的路易斯·冯·安、Manuel Blum、Nicholas J.Hopper以及IBM的John Langford所提出。卡内基梅隆大学曾试图申请此词使其成为注册商标, 但该申请于2008年4月21日被拒绝。一种常用的CAPTCHA测试是让用户输入一个扭曲变形的图片上所显示的文字或数字,扭曲变形是为了避免被光学字符识别(OCR, Optical Character Recognition)之类的电脑程序自动辨识出图片上的文数字而失去效果。由于这个测试是由计算机来考人类,而不是标准图灵测试中那样由人类来考计算机,人们有时称CAPTCHA是一种反向图灵测试。

    除了图形验证码之外,为了无法看到图像的身心障碍者,替代的方法是改用语音读出文数字,为了防止语音辨识分析声音,声音的内容会有杂音。当然,本篇博客只讨论图形验证码。

    总而言之,验证码是用来防止恶意登录、保护账号安全的。

     

    二、验证码登录的原理

    说了这么多,那我们到底如何编码实现验证码登录呢?

    其实验证码的原理并不复杂,实现起来主要有以下几个步骤:

    1. 后台生成验证码图片,同时将验证码中内容保存到服务器session中
    2. 前端登录时将验证码和用户名、密码一起提交到后台
    3. 后台验证前端输入的验证码和session中是否一致,如果一致则验证成功,进入步骤4;否则验证不成功,返回步骤1
    4. 验证用户名和密码,返回登录验证信息
    5. 若登录验证成功,则跳转到相应页面;否则在登录页面提示错误信息

    当然,一般验证码上还有个点击刷新获取新验证码的功能,其实就是验证码图片上有个点击事件(onClick),该事件调用后台获取验证码的方法获取新的验证码,与此同时,后台session中也更新为新的验证码。

    三、整合Kaptcha实现验证码校验登录

    温馨提示:我们本篇整合Kaptcha教程都是在本系列前面教程的基础上进行的,如果要完整实现功能的话,建议大家先看下《SSM整合》专栏前面的教程哦(☄⊙ω⊙)☄

    1. 首先要pom.xml中加入Kaptchar依赖

    <!-- 验证码工具 -->
    <dependency>
        <groupId>com.github.penggle</groupId>
        <artifactId>kaptcha</artifactId>
        <version>2.3.2</version>
    </dependency>

    2. 在login.jsp中加入验证码输入框和验证码展示图片,验证码图片<img>元素上指定了onclick方法:当点击验证码图片时调用changeVcode()来刷新验证码。

    <tr style="width: 100%">
        <td style="width: 70%">
            <div class="input-group" style="margin-bottom: 15px;width: 100%">
                <span class="input-group-addon" id="basic-addon-vcode">
                    <i class="glyphicon glyphicon-th-large"></i>
                </span>
                <input class="form-control" name="vcode" id="vcode" type="text" placeholder="请输入验证码" oninput="value=value.replace(/[^a-zA-Z0-9]+$/,'');if(value.length>5)value=value.slice(0,5)">
             </div>
         </td>
         <td style="width: 30%">
             <img src='<%=basePath%>/vcode' id="vcode_img" class="vcode_img" onclick="changeVcode($(this));" style="margin-top: -5px;"/>
         </td>
    </tr>

    3. changeVcode()方法。将<img>元素的src属性指定为从"/vcode"的Controller获取,后面加上当前日期时间戳作为参数的目的是为了防止浏览器缓存验证码,这样就不会引起点击后验证码不刷新的问题。

    function changeVcode(obj) {
        obj.attr("src", '<%=basePath%>/vcode?d=' + new Date().getTime());
    }

    4. KaptchaController.java。在controller包中新建KaptchaController.java文件,上面的"/vcode"controller就是写在这里,同时还要配置验证码的一些属性。文件代码如下:

    package com.oms.control;
    
    import com.google.code.kaptcha.Constants;
    import com.google.code.kaptcha.Producer;
    import com.google.code.kaptcha.impl.DefaultKaptcha;
    import com.google.code.kaptcha.util.Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.servlet.ModelAndView;
    import javax.imageio.ImageIO;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.image.BufferedImage;
    import java.util.Properties;
    
    /**
     * 登录验证码控制类
     */
    @Controller
    public class KaptchaController {
    
        @Autowired
        private Producer captchaProducer;
    
        /**
         * 方法名:生成二维码控制类
         * 创建人:yocco
         */
        @RequestMapping(value = "/vcode", method = RequestMethod.GET)
        public ModelAndView getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
            response.setDateHeader("Expires", 0);
            // Set standard HTTP/1.1 no-cache headers.
            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            // Set standard HTTP/1.0 no-cache header.
            response.setHeader("Pragma", "no-cache");
            // return a jpeg
            response.setContentType("image/jpeg");
            // create the text for the image
            String capText = captchaProducer.createText();
            // store the text in the session
            request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
            // create the image with the text
            BufferedImage bi = captchaProducer.createImage(capText);
            ServletOutputStream out = response.getOutputStream();
            // write the data out
            ImageIO.write(bi, "jpg", out);
            try {
                out.flush();
            } finally {
                out.close();
            }
            return null;
        }
    
        /**
         * 验证码配置
         */
        @Bean(name = "captchaProducer")
        public DefaultKaptcha getKaptchaBean() {
            DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
            Properties properties = new Properties();
            properties.setProperty("kaptcha.border", "yes");
            properties.setProperty("kaptcha.border.color", "105,179,90");
            properties.setProperty("kaptcha.textproducer.font.color", "blue");
            properties.setProperty("kaptcha.image.width", "125");
            properties.setProperty("kaptcha.image.height", "45");
            properties.setProperty("kaptcha.session.key", "code");
            properties.setProperty("kaptcha.textproducer.char.string", "0123456789"); //设定验证码的内容范围,这里指定只将0-9范围的数字作为验证码内容
            properties.setProperty("kaptcha.textproducer.char.length", "4");
            properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
            Config config = new Config(properties);
            defaultKaptcha.setConfig(config);
            return defaultKaptcha;
        }
    }

    上面getKaptcharBean()方法是用来指定验证码的一些属性,比如下面这一句设置了只将0-9的数字作为验证码内容,因此生成的验证码里只会有数字而不会有英文字符或其它内容。

    properties.setProperty("kaptcha.textproducer.char.string", "0123456789");

    5. login.jsp中的login()方法加上vcode参数传到后台进行校验。并且,当登录验证失败时,调用changeVcode()方法刷新验证码。

    function login() {
        var username = $('#username').val();
        var password = $('#password').val();
        var vcode = $('#vcode').val();
        //判断输入是否为空
        if (username == '' || password == '' || vcode == '') {
            alert('账号信息不能为空!');
            return;
        }
        $.ajax({
            type: 'post',
            url: '<%=basePath%>/user/checkLogin',
            cache: false,
            dataType: 'json',
            data: {username: username, password: password, vcode: vcode},
            success: function (data) {
                if (data.code == '0') {
                    window.location.href = '<%=basePath%>/index';
                } else {
                    changeVcode($('#vcode_img'));
                    $("#tips").css("visibility", "visible");
                    $('#tips').text(data.msg);
                }
             },
             error: function (data) {
                 alert('登录失败,请联系系统管理员');
             }
        })
    }

    6. "/user/checkLogin"controller中加上验证码校验

    @ResponseBody
    @RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
    public ResultObj checkLogin(HttpServletRequest request, HttpServletResponse response) {
        logger.info("/user/checkLogin ---> start");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String vcode = request.getParameter("vcode");
        //校验验证码
        if (OmsStringUtils.isNotEmpty(vcode)) {
            // 获取session中的验证码
            String sessionCode = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
            // 如果输入的验证码和会话的验证码不一致的,提示用户输入有误
            if (OmsStringUtils.isNotEmpty(sessionCode) && !vcode.equalsIgnoreCase(sessionCode)) {
                return new ResultObj("6", "验证码错误");
            }
        }
        //验证登录信息
        //验证用户名和密码
        //....(本处省略)
    
        logger.info("/user/checkLogin ---> end");
        return result;
    }

     

    四、本篇结束语

    验证码登录并不复杂,只要理清了原理和校验流程,实现起来就很容易了。不过没有实现的朋友也不要灰心,关注公众号「小白轻松学编程」留言交流。

    展开全文
  • 前言 本教程是基于 “apifm-wxapi” 模块,教你快速实现小程序开发,所以你可能需要先了解以下...图形验证码的使用场景很多,很多需要考虑安全的场合下都需要使用图形验证码来屏蔽机器人的自动化、批量操作; 本例...
  • 验证码功能提高了安全性,但是降低了用户体验,我在某些产品中,发现他们竟然没有用验证码了。只是在用户登陆失败一次之后,再次登陆再显示验证码来提高本次登陆安全性,但是本文只介绍验证码的实现,这种用户体验...
  • SpringBoot下实现前端验证码图片的生成和校验,供大家参考,具体内容如下1.效果点击验证码可以获取新的验证码2.原理后台生成验证码图片,将图片传到前台。 后台在session中保存验证码内容。 前台输入验证码后传到...
  • java验证码的编写和校验

    千次阅读 热门讨论 2016-07-25 10:22:44
    验证码是防止网站被恶意攻击的一种网络安全技术,通过验证码可以防止用户重复登录同一界面,同时也可以防止黑客编写的自动注册程序对网站的攻击。 实际上,验证码就是将一串随机产生的数字或符号,生成一幅图片,...
  • 以下代码是使用Cookie和Session的实例,其中使用Cookie进行登录勾选记住密码的任务,Session进行验证码的验证和安全退出的功能,验证码使用到了kaptcha,这是个第三方类库,需要的可以百度下载下来使用。 ...
  • 前台输入验证码后传到后台在后台取出session中保存的验证码进行校验。 注意,验证码的明文是不能传送到前端的。前端内容都是透明的,不安全验证码是用来防机器人并不是单单防人。如果把验证码明文传到前端很容易...
  • 验证码安全深度剖析

    千次阅读 2018-12-12 11:03:40
    验证码大家都比较熟悉,一般是为了防止暴力破解和机器的恶意注册,但是你的验证码安全吗? 前端绕过验证码 有些验证码是通过前台校验的,就是前台写一个生成验证码的函数,然后去跟用户输入做比较 就像这种我们...
  • 前言 本教程是基于 “apifm-wxapi” 模块,教你快速实现小程序开发,所以你可能需要先了解以下知识点: ...很多安全场合,都需要使用到短信验证码功能,来确保操作者是本人; 一般app都会使用 “手机号码 + 短信验证...
  • 接下来的两篇文章,我们主要介绍对app短信验证码安全进行测试。我们将通过burp软件的intruder模块模拟生成4位纯数字短信验证码测试app短信验证码安全性。我们要分析的app发送短信验证码的请求中带有sign签名校验,...
  • 文章目录一、暴力破解及验证码安全注意事项二、C/S架构暴力猜解三、B/S...安全0x01 验证码可重用0x02 验证码可识别0x03 客户端生成/显示/校验0x04 空验证码绕过0x05 验证码数量有限0x06 是否校验可控0x07 超过次数才...
  • SpringBoot下实现前端验证码图片的生成和校验   1.效果 点击验证码可以获取新的验证码 2.原理 后台生成验证码图片,将图片传到前台。 后台在session中保存验证码内容。 前台输入验证码后传到后台在后台...
  • 验证码在session 里面 可是校验成功之后没删除验证码 安全部门觉得有风险,然后研究了session repository 注入之后调用remove attribute 验证码 但是一直失败 后来才发现 httpsession里面的已经代理了session ...
  • 进入移动互联网时代,使用短信验证来校验身份已是非常普遍的方式,但是接收验证短信时间过长,安全性弱,是一道大难题。本机号码校验能力,将很好的为开发者们解决这一难题。
  • 中国移动推出的本机号码校验能力,用于验证用户本机号码与输入号码是否一致。App在登录的时候,不再需要接收验证短信,简简单单输入电话号码后立马校验,实现用户无感校验安全便捷。
  • “本机号码校验”最大优势是安全升级“本机号码校验”更多应用于风险控制场景我们的优势 卓望认证子产品除一键登录外,另一个拳头产品就是本机号码校验。 什么是“本机号码校验”? 本机号码校验通过手动输入...
  • 用户填写验证码后,就可以点击登录,登录的时候发送手机验证码和et_token校验请求。 所以总共需要发送两个请求。 请求方式是使用Xutils已经封装好的的http请求。可以点击查看:Android请求服务器获取短信验证码实现...
  • 包括web项目里面非常常用的重复性代码,如校验用户名、手机号、身份证号、密码、等等,是否符合安全规则。 生成绝不重复的订单号。 生成图片验证码。 json解析。 全是自己手写,供大家复用。
  • 验证码安全验证 前后端交互流程

    千次阅读 2018-01-10 15:33:53
    首先app发起请求,点击获取验证码,服务器返回响应头,头里拿到cookie,cookie里获取_PhoneVerifyCookie(是服务器对验证 码加密后的处理),然后app点注册,app拿着响应的_PhoneVerifyCookie...以此完成验证码校验
  • 如果没有做好逻辑判断,可以通过修改返回的数据包来实现绕过验证码安全防护 危害 绕过验证码的限制进行用户注册 任意用户密码重置 实现用户与任意手机号或邮箱绑定 漏洞原理 由于开发人员使用了错误的逻辑判断,...
  • php验证码生成与校验,Discuz验证码生成插件,拖动对照图形的验证码风格,拖动图形到指定位置即可完成验证,本验证码插件基于行为式验证技术的验证码discuz插件,可以直接安装在discuz网站中,作为网站的安全防护...
  • JS实现验证码

    千次阅读 2019-03-31 18:01:51
    温馨提示:不推荐使用下面方法(及前端验证码校验)进行校验,因为只进行前台验证而不进行后台服务器端的校验,黑客大咖们很容易攻破这道防线,不能够很好的保证网站的安全性。 <!Doctype html> <head>...
  • 文章目录开发生成图形验证码接口图片实体 ImageCode图片接口 ValidateCodeController在认证流程中加入图形验证码校验登录页面安全认证配置不拦截图片路径测试 图片路径无法访问404及解决访问自定义过滤器 ...
  • java 滑动验证码

    千次阅读 2019-08-27 11:05:03
    验证码的生成与校验可在前端也可以在后端,但是为了安全考虑,一般将验证码的的生成与校验放置在后台,防止被暴力破解。这里先介绍一波图片的滑块验证: 准备工作: 六张像素为290*147的图片 思路: 后台获取源图片...
  • 一般来说,验证码校验前端后台都要检验一次。这才比较安全。 可是现在问题是这样的: 我有一个action是提供给自己业务系统调用,同时也提供给别的系统通过httpclient的方式调用。 在这个action里面,是需要做验证码...
  • 1.会话技术 会话技术是帮助服务器 记住客户端状态(区分客户端) 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话 ...Session:将数据存储到服务器端,安全性相对好,增...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 232
精华内容 92
关键字:

安全验证码校验