精华内容
下载资源
问答
  • 本产品采用阿里AI技术结合人工智能核心技术。你制作好静态固定金额收款二维码无需自己做任何操作处理,完全智能化自动识别采用多线程技术稳定提升识别速度,功能非常强大... 您还在等什么呢!心动还不如行动,赶快...
  • 由于QRCode方式生成二维码解析二维码不在一个Jar包内,而且获取的网址也不一样,因此我们需要去两个网址获取这两个Jar包。  首先是获取生成QRCode二维码的Jar包,大家可以访问...

          由于QRCode方式生成二维码和解析二维码不在一个Jar包内,而且获取的网址也不一样,因此我们需要去两个网址获取这两个Jar包。

    第一步:获取生成二维码的Jar包

          首先是获取生成QRCode二维码的Jar包,大家可以访问http://www.swetake.com/qrcode/index-e.html这个网址,如下图所示。我们点击标注的那个链接。


            我们会看到如下图所示界面,这是个日文的网站,不用管它,找到下图标注的那个链接,点击它。


           会看到如下图所示,点击标注的链接。


           下载完之后,解压文件,如下图所示。


              我们进入qrcode_java0.50beta10文件夹当中,找到lib目录,lib目录下有Qrcode.jar文件,如下图所示。


             由于QRCode生成二维码的Jar包和接卸二维码的Jar包名字相同,但包不相同,因此为了避免冲突,给生成二维码的Jar改名为Qrcode-C.jar(C代表Create的意思)。如下图所示。这样我们便得到了生成二维码的Jar包了。


    第二步:获取解析二维码的Jar包

            首先在地址栏输入https://osdn.jp/projects/qrcode/,我们会看到如下图所示界面,我们下载最新的版本(下图标注的链接)。


              

             我们会看到如下图所示界面,点击"qrcode.zip"。


             下载完后解压qrcode.zip,如下图所示。


             进入qrcode目录,找到lib目录,可以看到解析二维码的Jar包qrcode.jar,如下图所示。


            与生成二维码的Jar包命名规则一样,我们也给这个jar包起个名字qrcode-R.jar(R的意思是阅读、解析)。这样,生成二维码和解析二维码的Jar包就都有了。



    展开全文
  • QRCode 生成二维码

    2017-05-11 13:15:05
    QRCode生成二维码直接百度下载路径:...QRCode解析二维码直接百度下载路径:链接: https://pan.baidu.com/s/1nuElTYp 密码: hfur 生成二维码的下载 第一步:复制下载链接:http://www.swetake.com/qrcode/index-e.htm

    QRCode生成二维码直接百度云下载路径:链接: https://pan.baidu.com/s/1i4VVbdb 密码: bshi

    QRCode解析二维码直接百度云下载路径:链接: https://pan.baidu.com/s/1nuElTYp 密码: hfur

    生成二维码的下载

    第一步:复制下载链接:http://www.swetake.com/qrcode/index-e.html在浏览器中打开,点击红框内的连接(document & libraries ......)



    第二步:点击后进入页面,点击红框内的连接(上面两个是其他语言的,我们选择java)



    第三步:直接点击红框内的下载



    第四步:下载后,解压缩后的包展示



    解析二维码的下载

    复制下载链接:https://zh.osdn.net/projects/qrcode/    因为内容是中文的,而且步骤简单,在这就不详细介绍了.


    把下载下来的压缩包中的lib文件夹中的jar拷贝到项目中,注意修改一下名字,两个jar包名字一样,但是里面的类不一样,也可手动自己合并.

    如果是maven项目到repository中搜索QRCode找到相关依赖

    JAVA代码生成二维码

    package com.crazy_qu.QRCode;
    
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    
    import javax.imageio.ImageIO;
    
    import com.swetake.util.Qrcode;
    /**
     * QRCode生成二维码
     * @author crazy
     *
     */
    public class CreateQRCode {
    
    	public static void main(String[] args) throws Exception {
    		Qrcode x=new Qrcode();//二维码类,对内容填充
    		x.setQrcodeErrorCorrect('M');//纠错等级LMQH
    		x.setQrcodeEncodeMode('B');//N代表数字, A代表a-Z, B代表其他字符
    		x.setQrcodeVersion(7);//QRCode的版本号,取值1-40
    		
    		String qrData = "www.baidu.com";
    		int width = 67 + 12 * (x.getQrcodeVersion() - 1);//不通过这个计算,直接写一个设定值,二维码显示位置有误
    		int height = 67 + 12 * (x.getQrcodeVersion() - 1);
    		
    		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//缓冲区的图片
    		Graphics2D gs = bufferedImage.createGraphics();//java画图工具
    		
    		gs.setBackground(Color.WHITE);//背景色
    		gs.setColor(Color.BLACK);//设置二维码颜色
    		gs.clearRect(0, 0, width, height);//清除画板内容
    		
    		int pixoff = 2;//偏移量
    		
    		byte[] d =qrData.getBytes("gb2312");//转换成字节数,如果存在汉字使用"gb2312"字符集
    		if (d.length>0 && d.length <120){
    		    boolean[][] s = x.calQrcode(d);
    
    		    for (int i=0;i<s.length;i++){
    				for (int j=0;j<s.length;j++){
    				    if (s[j][i]) {
    				    	gs.fillRect(j*3 + pixoff ,i*3 + pixoff , 3, 3);//添加偏移量,否则有时解析会出错
    				    }
    				}
    		    }
    		}
    		gs.dispose();
    		bufferedImage.flush();
    		
    		ImageIO.write(bufferedImage, "png", new File("D:/qrcode.png"));
    	}
    }
    

    JAVA代码解析二维码

    package com.crazy_qu.QRCode;
    
    import java.awt.image.BufferedImage;
    
    
    public class QRCodeImage implements jp.sourceforge.qrcode.data.QRCodeImage {
    
    	private BufferedImage bufferedImage;
    	
    	public  QRCodeImage(BufferedImage bufferedImage) {
    		this.bufferedImage = bufferedImage;
    	}
    
    	@Override
    	public int getHeight() {
    		return bufferedImage.getHeight();
    	}
    
    	@Override
    	public int getPixel(int arg0, int arg1) {
    		return bufferedImage.getRGB(arg0, arg1);
    	}
    
    	@Override
    	public int getWidth() {
    		return bufferedImage.getWidth();
    	}
    
    }
    

    package com.crazy_qu.QRCode;
    
    import java.awt.image.BufferedImage;
    import java.io.File;
    
    import javax.imageio.ImageIO;
    
    import jp.sourceforge.qrcode.QRCodeDecoder;
    
    public class ReadQRCode {
    
    	public static void main(String[] args) throws Exception {
    		//指定文件位置
    		File file = new File("D:/qrcode.png");
    		//读取文件
    		BufferedImage bufferedImage = ImageIO.read(file);
    		
    		QRCodeDecoder codeDecoder = new QRCodeDecoder();//QRCode译码器
    		String result = new String(codeDecoder.decode(new QRCodeImage(bufferedImage)), "gb2312");
    		
    		System.out.println(result);
    	}
    }
    







    展开全文
  • 二维码自动扫描完整版

    千次阅读 2017-07-20 17:52:32
    二维码扫描
    关闭

    android中Zxing实现二维码功能的快速集成以及扫描界面的定制

    标签: 二维码android
    5179人阅读 评论(14) 收藏 举报
    分类:

    Zxing二维码库是相当丰富。但是我们往往只需要里面的扫码识别以及生成二维码的功能就可以了,所以这次用到了已经抽离出核销代码的框架包
    compile ‘com.journeyapps:zxing-android-embedded:3.3.0’,来快速集成开发。比较简单,后面还会有扫面界面的定制,仿微信二维码扫一扫功能。上几个效果图:
    扫描中
    这里写图片描述
    扫描结果:
    这里写图片描述
    接下来我们来实现他。
    一、集成二维码的简单扫一扫以及生成二维码的功能(录屏用的是genymotion,录的有点奇怪啊)
    这里写图片描述
    1、Zxing二维码的环境。我们只要compile ‘com.journeyapps:zxing-android-embedded:3.3.0’这个后面就不需要再集成了。
    2、xml文件中

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical">
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="打开闪关灯"
            android:id="@+id/btn_switch"
            android:layout_alignTop="@+id/btn_hint1"
             />
        <!-- 这个控件就是扫描的窗口了 -->
        <com.journeyapps.barcodescanner.DecoratedBarcodeView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/dbv_custom"
            app:zxing_framing_rect_width="200dp"
            app:zxing_framing_rect_height="200dp"
            app:zxing_preview_scaling_strategy="fitXY"
            app:zxing_use_texture_view="true"
           >
        </com.journeyapps.barcodescanner.DecoratedBarcodeView>
    
    </LinearLayout>

    3、CustomScanAct.java

    package com.coofond.zxingdemo;
    
    import android.app.Activity;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.os.PersistableBundle;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    
    import com.journeyapps.barcodescanner.CaptureManager;
    import com.journeyapps.barcodescanner.DecoratedBarcodeView;
    
    /**
     * Created by IBM on 2016/10/13.
     */
    
    public class CustomScanAct extends Activity implements DecoratedBarcodeView.TorchListener { // 实现相关接口
        // 添加一个按钮用来控制闪光灯,同时添加两个按钮表示其他功能,先用Toast表示
        Button swichLight;
        DecoratedBarcodeView mDBV;
        private CaptureManager captureManager;
        private boolean isLightOn = false;
    
    
        @Override
        protected void onPause() {
            super.onPause();
            captureManager.onPause();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            captureManager.onResume();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            captureManager.onDestroy();
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
            super.onSaveInstanceState(outState, outPersistentState);
            captureManager.onSaveInstanceState(outState);
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            return mDBV.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.act_customscan);
            swichLight = (Button) findViewById(R.id.btn_switch);
            mDBV= (DecoratedBarcodeView) findViewById(R.id.dbv_custom);
    
            mDBV.setTorchListener(this);
    
            // 如果没有闪光灯功能,就去掉相关按钮
            if (!hasFlash()) {
                swichLight.setVisibility(View.GONE);
            }
            //重要代码,初始化捕获
            captureManager = new CaptureManager(this, mDBV);
            captureManager.initializeFromIntent(getIntent(), savedInstanceState);
            captureManager.decode();
            //选择闪关灯
            swichLight.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isLightOn) {
                        mDBV.setTorchOff();
                    } else {
                        mDBV.setTorchOn();
                    }
                }
            });
        }
    
        // torch 手电筒
        @Override
        public void onTorchOn() {
            Toast.makeText(this, "torch on", Toast.LENGTH_LONG).show();
            isLightOn = true;
        }
    
        @Override
        public void onTorchOff() {
            Toast.makeText(this, "torch off", Toast.LENGTH_LONG).show();
            isLightOn = false;
        }
    
        // 判断是否有闪光灯功能
        private boolean hasFlash() {
            return getApplicationContext().getPackageManager()
                    .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
        }
    
    
    
    }
    

    4、MainActivity.java

    package com.coofond.zxingdemo;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.google.zxing.integration.android.IntentIntegrator;
    import com.google.zxing.integration.android.IntentResult;
    
    public class MainActivity extends Activity {
        private Button btnClick;
        private TextView tvResult;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            initEvent();
        }
    
        private void initView() {
            btnClick = (Button) findViewById(R.id.btn_click);
            tvResult = (TextView) findViewById(R.id.tv_result);
        }
    
        private void initEvent() {
            btnClick.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //假如你要用的是fragment进行界面的跳转
                    //IntentIntegrator intentIntegrator = IntentIntegrator.forSupportFragment(ShopFragment.this).setCaptureActivity(CustomScanAct.class);
                    IntentIntegrator intentIntegrator = new IntentIntegrator(MainActivity.this);
                    intentIntegrator
                            .setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES)
                            .setPrompt("将二维码/条码放入框内,即可自动扫描")//写那句提示的话
                            .setOrientationLocked(false)//扫描方向固定
                            .setCaptureActivity(CustomScanAct.class) // 设置自定义的activity是CustomActivity
                            .initiateScan(); // 初始化扫描
                }
            });
        }
    
        //获取扫描的结果
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            IntentResult intentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
            if (intentResult != null) {
                if (intentResult.getContents() == null) {
    
                } else {
                    // ScanResult 为获取到的字符串
                    String ScanResult = intentResult.getContents();
                    tvResult.setText(ScanResult);
                }
            } else {
                super.onActivityResult(requestCode, resultCode, data);
            }
        }
    }
    

    这样就集成了二维码的基本功能了。显示的是一个闪动的激光条。。。

    二、仿造微信扫一扫,重新定制扫面界面,看下要实现的效果图
    这里写图片描述

    1、主要是这一句 app:zxing_scanner_layout=”@layout/barcode_scanner”指向你自定义的界面

     <!-- 这个控件就是扫描的窗口了 -->
        <com.journeyapps.barcodescanner.DecoratedBarcodeView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/dbv_custom"
            app:zxing_framing_rect_width="200dp"
            app:zxing_framing_rect_height="200dp"
            app:zxing_preview_scaling_strategy="fitXY"
            app:zxing_use_texture_view="true"
            app:zxing_scanner_layout="@layout/barcode_scanner"
           >
        </com.journeyapps.barcodescanner.DecoratedBarcodeView>

    2、那么我们看下如何定制这个窗口barcode_scanner.xml看一下

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        >
        <com.journeyapps.barcodescanner.BarcodeView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/zxing_barcode_surface"
            app:zxing_framing_rect_width="250dp"
            app:zxing_framing_rect_height="250dp">
        </com.journeyapps.barcodescanner.BarcodeView>
    
        <com.coofond.zxingdemo.CustomViewfinderView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/zxing_viewfinder_view"
            app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
            app:zxing_result_view="@color/zxing_custom_result_view"
            app:zxing_viewfinder_laser="#FFFFFF"
            app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
    
        <TextView
            android:id="@+id/zxing_status_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:background="@color/zxing_transparent"
            android:text="@string/zxing_msg_default_status"
            android:textColor="@color/zxing_status_text"/>
    
    </merge>

    3、主要是要自定义ViewfinderView,重新绘制你的扫描界面。看下CustomViewfinderView.java中的文件

    package com.coofond.zxingdemo;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.LinearGradient;
    import android.graphics.Rect;
    import android.graphics.Shader;
    import android.util.AttributeSet;
    
    import com.google.zxing.ResultPoint;
    import com.journeyapps.barcodescanner.ViewfinderView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 自定义zxing二维码扫描界面
     * Created by IBM on 2016/10/20.
     */
    
    public class CustomViewfinderView extends ViewfinderView {
        public int laserLinePosition=0;
        public float[] position=new float[]{0f,0.5f,1f};
        public int[] colors=new int[]{0x00ffffff,0xffffffff,0x00ffffff};
        public LinearGradient linearGradient ;
        public CustomViewfinderView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
    
        /**
         * 重写draw方法绘制自己的扫描框
         * @param canvas
         */
        @Override
        public void onDraw(Canvas canvas) {
            refreshSizes();
            if (framingRect == null || previewFramingRect == null) {
                return;
            }
    
            Rect frame = framingRect;
            Rect previewFrame = previewFramingRect;
    
            int width = canvas.getWidth();
            int height = canvas.getHeight();
            //绘制4个角
    
            paint.setColor(0xFFFFFFFF);//定义画笔的颜色
            canvas.drawRect(frame.left, frame.top, frame.left+70, frame.top+10, paint);
            canvas.drawRect(frame.left, frame.top, frame.left + 10, frame.top + 70, paint);
    
            canvas.drawRect(frame.right-70, frame.top, frame.right, frame.top+10, paint);
            canvas.drawRect(frame.right-10, frame.top, frame.right, frame.top+70, paint);
    
            canvas.drawRect(frame.left, frame.bottom-10, frame.left+70, frame.bottom, paint);
            canvas.drawRect(frame.left, frame.bottom-70, frame.left+10, frame.bottom, paint);
    
            canvas.drawRect(frame.right-70, frame.bottom-10, frame.right, frame.bottom, paint);
            canvas.drawRect(frame.right-10, frame.bottom-70, frame.right, frame.bottom, paint);
            // Draw the exterior (i.e. outside the framing rect) darkened
            paint.setColor(resultBitmap != null ? resultColor : maskColor);
            canvas.drawRect(0, 0, width, frame.top, paint);
            canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
            canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
            canvas.drawRect(0, frame.bottom + 1, width, height, paint);
    
            if (resultBitmap != null) {
                // Draw the opaque result bitmap over the scanning rectangle
                paint.setAlpha(CURRENT_POINT_OPACITY);
                canvas.drawBitmap(resultBitmap, null, frame, paint);
            } else {
                //  paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
                //  scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
                int middle = frame.height() / 2 + frame.top;
                laserLinePosition=laserLinePosition+5;
                if(laserLinePosition>frame.height())
                {
                    laserLinePosition=0;
                }
                linearGradient= new LinearGradient(frame.left + 1, frame.top+laserLinePosition , frame.right -1 , frame.top +10+laserLinePosition, colors, position, Shader.TileMode.CLAMP);
                // Draw a red "laser scanner" line through the middle to show decoding is active
    
                //  paint.setColor(laserColor);
                paint.setShader(linearGradient);
                //绘制扫描线
                canvas.drawRect(frame.left + 1, frame.top+laserLinePosition , frame.right -1 , frame.top +10+laserLinePosition, paint);
                paint.setShader(null);
                float scaleX = frame.width() / (float) previewFrame.width();
                float scaleY = frame.height() / (float) previewFrame.height();
    
                List<ResultPoint> currentPossible = possibleResultPoints;
                List<ResultPoint> currentLast = lastPossibleResultPoints;
                int frameLeft = frame.left;
                int frameTop = frame.top;
                if (currentPossible.isEmpty()) {
                    lastPossibleResultPoints = null;
                } else {
                    possibleResultPoints = new ArrayList<>(5);
                    lastPossibleResultPoints = currentPossible;
                    paint.setAlpha(CURRENT_POINT_OPACITY);
                    paint.setColor(resultPointColor);
                    for (ResultPoint point : currentPossible) {
                        canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
                                frameTop + (int) (point.getY() * scaleY),
                                POINT_SIZE, paint);
                    }
                }
                if (currentLast != null) {
                    paint.setAlpha(CURRENT_POINT_OPACITY / 2);
                    paint.setColor(resultPointColor);
                    float radius = POINT_SIZE / 2.0f;
                    for (ResultPoint point : currentLast) {
                        canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
                                frameTop + (int) (point.getY() * scaleY),
                                radius, paint);
                    }
                }
                postInvalidateDelayed(16,
                        frame.left ,
                        frame.top ,
                        frame.right ,
                        frame.bottom);
                // postInvalidate();
    
            }
        }
    }
    

    那么就完全结束了。是懂非懂的感觉。只是停留在集成和使用的阶段。
    最后该demo的下载地址http://download.csdn.net/detail/z_zt_t/9659802

    7
    0
     
     

    猜你在找
    C语言及程序设计(讲师:贺利坚)
    Python爬虫工程师培养课程全套(讲师:韦玮)
    Python全栈开发入门与实战课(讲师:李杰)
    2017软考网络规划设计师视频套餐(讲师:任铄)
    2017软考软件设计师视频套餐(讲师:任铄)
    2017软考-信息系统项目管理师视频套餐(讲师:任铄)
    软考(高级)项目经理实战营(讲师:张传波)
    微信公众平台开发套餐(讲师:刘运强)
    深度学习原理+实战+算法+主流框架套餐(讲师:唐宇迪)
    2017系统集成项目管理工程师通关套餐(讲师:徐朋)
    查看评论
    * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    • 个人资料
      • 访问:63338次
      • 积分:1496
      • 等级:
        积分:1496
      • 排名:千里之外
      • 原创:75篇
      • 转载:14篇
      • 译文:0篇
      • 评论:52条
    • 最新评论
    收藏助手
    展开全文
  • 二维码扫码登录原理

    千次阅读 2020-05-04 18:10:57
    简要明了,步步深入,图文并茂地解析二维码扫码登录原理,让你在相同或相似的业务场景中安全可靠的实现二维码扫码登录。

     

     

    简介


    二维码扫码登录这个操作,在我们的日常生活和工作中频频出现。

    这种操作主要发生于:在手机设备已经登录的情况下,需要在电脑PC端应用或者网页应用也登录,这时,如果该应用支持扫码登录,我们就可以用手机端的应用来扫描PC端生成的一个二维码,进而进行登录。如下图所示:

     

    比如我们每个人几乎都会接触过的:

    微信扫码登录、QQ扫码登录、网易云音乐扫码登录、百度网盘扫码登录等等。

     

    首先,我们来简单描述一下扫码登录这个流程,用微信登录进行举例:

    假设:手机端已经登录了微信,这时需要在PC端登录

    (1)PC端生成一个二维码,等待扫描

    (2)使用手机端微信的扫一扫功能扫码二维码

    (3)手机端解析二维码并弹出确认登录弹窗,此时PC端的二维码状态显示为:已扫描,等待确认

      (4) 手机端点击确认登录,这时PC端的微信完成登录

     

    分析


    以上几个大体步骤就是我们进行扫码登录的一个基本流程。那么,我们要如何去设计这么一个功能呢?

    在开始设计之前,我们需要思考明白一下几个关键点:

    • 在手机端进行确认登录的时候,为什么PC端就能直接登录?

    • 在扫码登录整个过程中,手机端和PC端是否需要有数据传输(如用户ID或者用户名+密码)?

    • 如何保证扫码登录的过程是安全的,非信息暴露泄漏的?

    • PC端是如何检测到二维码的状态的(已扫描、已取消、已确认等)?

     

    首先,前两个问题我们一起综合分析:

    在扫码登录过程中,需要明确的是,手机端和PC端是肯定有数据交互的,不然PC端是无法登录得了的。那双端交互的这个数据会是用户ID或者用户名密码吗?

    先排除后者,传输用户名密码最大的缺点就是用户敏感信息可能会造成泄漏,其次是,我们平常输入用户名密码登录,是客户端传输数据到服务器,然后在服务器进行校验并存储。但是这里如果传输用户名密码,就是从服务器传到PC客户端,然后PC客户端拿到后又原样不变地发送给服务器进行登录,这很明显逻辑奇怪并且流程冗余,会造成一定的服务器资源浪费;

    那会是传输用户ID吗?在理解不传输用户名密码的第二个原因后,那么也很容易明白,显然也不能或者不会传输用户ID。PC客户端虽然可以使用服务器返回的用户ID进行用户信息状态查询、同步等操作,但是直接拿用户ID进行一个“登录操作”,相当于跳过了token机制,那么以后在PC端的登录状态就没有过时的说法了,用户ID是一直不变的,只要客户端保存着这个ID,就可已拿这个ID进行登录验证,这显然不合理也不安全的。因此,也不可能是传输用户的ID。

     

    那到底是什么数据在进行交互呢?

    答案是:一种仅用于扫码登录的临时token令牌数据

    PC端在选择使用二维码登录的时候,服务器会生成一个二维码,并且这个二维码绑定着一个ID(二维码ID),当手机设备扫描二维码后,会解析二维码并拿到这个ID;然后当手机端点击确认登录后,手机端会带着这个ID,以及手机端上已经登录了的用户身份信息token,一起发送给服务器,服务器接收到后,新生成一个专门给PC端使用且绑定了用户身份的token,然后返回给PC端,这样PC端就相当于登录了,之后PC端的用户检验就是用这个token进行。当然,这里已经忽略了很多细节过程,下文会更加详细地流程描述。

    其实这里,已经回答了第三个问题:如何保证扫码登录的过程是安全的,非信息暴露泄漏的?

    在整个扫码登录过程中,手机端与PC端涉及的数据交互,仅仅是由服务器管理控制的一个二维码ID、手机端上的用户身份token(有时效性)、服务器新生成给PC端的用户身份token(有时效性),没有敏感信息交互,也就不存在敏感信息的泄漏;服务器给PC端生成一个新的token,从另一个角度上看,就跟用户输入用户名密码登录的本质是一样的,都是基于带时效性的token校验机制,只不过扫码登录的方式少了输入用户名密码这一个步骤。因此,这样的一个扫码登录流程是安全的。

     

    最后一个问题,PC端是如何检测到二维码的状态的呢?

    其实这里应该很容易就能想到了,无非两种:socket和轮询

     

    socket方式:

    PC端保持着与服务器的长连接,当手机端扫描二维码后,带着解析得到的二维码ID第一次发送给服务器,当服务器收到这个请求后,代表用户已经扫描了二维码,这时服务器就可以通过socket告知PC端二维码已被扫描,等待确认;之后手机端不论是取消登录还是确认登录,都会相应的请求服务器,服务器收到请求会根据相应的逻辑处理,进而通知PC端更新相应的状态,流程图如下:

     

    轮询方式:

    轮询方式即在PC端创建一个定时器,每隔一段时间请求服务器查询状态的更新情况,然后更新网页的显示信息。当时这个定时器得控制好启动时机和生命周期,因为PC端的二维码有可能一直没有被扫描,或者扫描之后没有下一步操作了,这时,如果没有控制好这个定时器,PC端就会一直地请求服务器查询,造成资源浪费和一定的性能损耗。

    轮询的流程如下图所示:

     

    至此,二维码扫码登录的分析我们已经基本了解了,接下来我们用时序图来描述二维码扫码登录的详细流程:

    当然,这里还有一些其他细节处理没有在时序图中标注出来,比如说当用户不是点击确认而是点击了取消,那么服务器也要做相应的处理,如将所有临时数据清除,并告知PC端二维码状态。这种时候,PC端那边的二维码就已经无效了,此时如果要重新进行二维码登录,则要重新进行上述时序图的操作。

     

    本文到这里就结束啦~欢迎各位读者伙伴们的点评和提供意见哦!

     

     

    展开全文
  • small-applications ...二维码生成 app包解析工具 逆向工程 rabbitmq处理请求日志 webservice发布和调用 扫码登陆 sql日志控制台打印显示出来 阿里文件上传 阿里短信发送 quartz动态定时任务,添加、删除任务
  • 二维码现在很常见, App中有许多都配置了该功能, 网上也有很多对iOS二维码的讲解, 但是对配置扫码范围这个问题好像都没怎么讲清晰. 作者今天就写一下二维码. 一 二维码介绍 二维码 三个回形大方块, 是...
  • 在 iOS 平台上本模块底层集成了 Zbar 和系统自带的条形码/二维码分析库,由于 IOS 系统平台在 IOS7.0 以上才开放了二维码/条码的相关接口,所以在 IOS6 上运行时模块会调用开源库 Zbar 去读取解析二维码/条码。...
  • 作者 |ask_the_sky来源 |https://juejin.cn/post/6940976355097985032前几天看了一个二维码的视频,写的不错,这里总结下。在日常生活中...
  • 使用zxing生成彩色或带图片的二维码

    千次阅读 2018-03-18 22:55:18
    一、zxing api的pom依赖 com.google.zxing core 3.3.0 com.google.zxing javase 3.3.0 二、生成普通的二维码 package com.mengfei.util; import com.google.
  • iOS 原生二维码[扫码]与[生成]详解

    千次阅读 2017-07-10 22:36:02
    二维码现在很常见, App中有许多都配置了该功能, 网上也有很多对iOS二维码的讲解, 但是对配置扫码范围这个问题好像都没怎么讲清晰. 作者今天就写一下二维码. 一 二维码介绍 二维码 三个回形大方块, 是...
  • # 首先导入本次所需要的库,最后一个csv是Python自带的csv表格操作库,这里我们需要把我们扫到的二维码信息都存入csv表格里。 import cv2 from pyzbar import pyzbar import csv # 然后我们设置一个变量,来存放...
  • 用OpenCV和Python识别二维码和条形码

    千次阅读 2019-12-20 12:51:33
    导读:计算机视觉专家Adrian Rosebrock近日分享了如何借助OpenCV和Zbar,编写出能够实时识别二维码和条形码的扫描程序,最后部署在树莓派上,成功制作一款实用的条形码&二维码扫描设备。 最近有朋友问我...
  • 深入解析云存储

    2019-03-21 18:00:00
    存储在云计算概念上延伸和发展出来的一个新的概念。云计算是是分布式处理、并行处理和网格计算的发展,是透过网络将庞大的计算处理程序自动分拆成无数个较小的子程序,再交由多部服...
  • FNScanner 模块是一个二维码/条形码扫描,是 scanner 模块的优化升级版。在 iOS 平台上本模块底层集成了 Zbar 和系统自带的条形码/二维码分析库,由于 IOS 系统平台在 IOS7.0 以上才开放了二维码/条码的相关接口,...
  • 现在大街小巷、各大网站都有二维码的踪迹,不管是IOS、Android、WP都有相关支持的软件。之前我就想了解二维码是如何工作,最近因为工作需要使用相关技术,所以做了初步了解。今天主要是讲解如何使用ZXing库,生成和...
  • 前言现如今围绕微信生态相关开发已经非常常见,本期带来如何通过qrcode.js实现微信内置浏览器动态生成二维码并能够长按识别 以及 通过html2canvas生成图片并长按保存说...
  • } /** * 解析短链接并跳转页面 * * @param shortUrl 短链接参数 */ @RequestMapping("/{shortUrl}") public void redirectToSourceUrl(@PathVariable("shortUrl") String shortUrl, HttpServletResponse response) ...
  • 4. 个推SDK解析定制数据,并且把第三方服务器透传的数据发送给第三方客户端,第三方客户端根据服务器的数据做出相应的动作或者展现。  五、google语音识别技术 原理 在Android 4.1中,Google...
  • 券后课程仅需 99 元 课程永久有效,随时回看 每节课仅需0.3元 扫描下方二维码,了解课程详情↓↓↓ windows和Mac都适用哦 课程内容永久保存、无限回看 280节超大容量 WPS-Office软件六合一 课程内容包含了Word/PPT/...
  • 在18日进行的“平台应用选型与建设实践”专场中,来自青云、腾讯、海云捷迅、微软、听、SpeedyCloud和七牛的7位工程师及技术专家分享了各自在技术实践中的心得与体会,其中内容涉及SDN架构、VPC网络架构、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,563
精华内容 2,225
关键字:

二维码云解析器