IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 扫码登录案例 -> 正文阅读

[移动开发]Android 扫码登录案例

首先不妨先看下Android:扫描二维码登陆原理:
在这里插入图片描述
大概总结下这个过程就是:

  1. 服务器生成全局唯一会话ID,并返回二维码、过期时间;
  2. 用户扫描二维码,提交改会话ID,用户基本信息到服务器;
  3. PC端在过期时间内一直轮询,如果用户扫码,服务器记录状态,PC端跳转到已登录页面;

那不妨按照这个思路来写一个简单的Demo

1. 后台

首先,我们需要搭建一个简易版的后台。在IDEA中创建SpringBoot项目,然后添加thymeleaf和session的依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-core</artifactId>
</dependency>

然后,我们这里模拟Demo,不需要数据库,故而模拟系统中已注册用户,可以使用Set集合来存储。模拟记录系统登录用户来使用Map存储。然后将之封装到一个Bean对象中。同样二维码这里也直接使用一张静态二维码,内容为:

http://192.168.1.102:8080/scanlogin?uuid=Wxfsfdfskfj==
@Component
public class UserMap {
    private static Map<String, User> loginmap = new HashMap<String, User>();
    private static Set<User> users = new HashSet<>();

项目结构如下:
在这里插入图片描述

添加对应的html页面,在loginpage.html中显示二维码,并进行轮询:

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <center>
        <div>login page!</div>
        <img src="code.png" style="width=300px; height=300px;">
        <div style="color:red;" id="info"></div>
    </center>
    <script>
        var getting = {
            url:'http://192.168.1.102:8080/checkscan',
            data:{
                "uuid": "Wxfsfdfskfj=="
            },
            dataType:'text',
            success:function(res) {
                if(JSON.parse(res)){
                    $('#info').html("已授权");
                    setTimeout(function(){
                        window.location.href = 'http://192.168.1.102:8080/home';
                    },1000);
                }
                else{
                    $('#info').html("未授权");
                }
                setTimeout(function(){
                    $.ajax(getting);
                },1000);
            },
            error:function(res){
                $('#info').html("请求发生了未知错误!");
            }
        };
        $.ajax(getting)
    </script>
</body>
</html>

然后就是Controller的Android端扫码后确认授权接口:

@GetMapping(value="/scanlogin")
@ResponseBody
// 手机端确定登录后调用该接口,将用户加入到登录Map
// http://localhost:8080/login?uuid=Wxfsfdfskfj==&userid=qwe&username=123
public String scanLogin(HttpSession session,
                           @RequestParam("uuid") String uuid,
                           @RequestParam("userid") String userid,
                           @RequestParam("username") String name){
    String UUID = "Wxfsfdfskfj==";
    User user = new User(name, userid);
    if(uuid.equals(UUID) && userService.checkUserInfo(user)){
        UserMap.loginUser(UUID, new User(name, userid));
        return "SUCCESS LOGIN!";
    }else {
        return "ERROR UserInfo!";
    }
}

在请求主页home的时候,需要判断用户是否登录,即校验Session

@GetMapping(value="/home")
// 校验Session的主页
public String getHomePage(HttpSession session){
    String username = (String) session.getAttribute("name");
    if(username == null){
        return "redirect:/notlogin";
    }
    return "homepage";
}

前端ajax轮询接口:

@GetMapping(value="/checkscan")
@ResponseBody
// 需要前端轮询这个接口,判断是否确认登录
public boolean hasScan(HttpSession session,
                      @RequestParam("uuid") String uuid){
    User scanedUser = UserMap.getScanUserByUUID(uuid);
    if(scanedUser == null)
        return false;
    if(userService.hasUser(scanedUser.getUserID())){
        String username = (String) session.getAttribute("name");
        if(username == null){
            session.setAttribute("name", uuid);
        }
        return true;
    }
    return false;
}

2. Android端

首先添加两个依赖:

implementation 'cn.yipianfengye.android:zxing-library:2.2'
implementation 'com.squareup.okhttp3:okhttp:3.2.0'

zxing是一个使用非常简单的扫码封装。项目地址:here

按照文档说明进行集成即可。页面非常简单,两个页面:
MainActivity中显示一个按钮,模拟扫码入口,调用后扫码后返回结果;
在这里插入图片描述

LoginActivity中进行提示用户确认授权,进行确认接口请求;
在这里插入图片描述
MainActivity中添加权限申请:

<uses-permission android:name="android.permission.CAMERA" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.INTERNET" />
// 请求读写权限
if (ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
    //申请权限
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[]{Manifest.permission.CAMERA}, 1);
}
if (ContextCompat.checkSelfPermission(MainActivity.this,
        Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
    //申请权限
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[]{Manifest.permission.INTERNET}, 1);
}

进行点击按钮的跳转

Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
startActivityForResult(intent, 1);

复写onActivityResult方法(CaptureActivity中调用setResult,然后finish()):

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    //处理扫描结果(在界面上显示)
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == 1){
        Toast.makeText(this, String.valueOf(null != data), Toast.LENGTH_LONG).show();
        if (null != data) {
            Bundle bundle = data.getExtras();
            if (bundle == null) {
                return;
            }
            if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
                String result = bundle.getString(CodeUtils.RESULT_STRING);
                Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                intent.putExtra("url", result);
                startActivity(intent);
            } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) {
                Toast.makeText(MainActivity.this, "解析二维码失败", Toast.LENGTH_LONG).show();
            }
        }
    }
}

在启动的LoginActivity中进行确认授权接口进行GET请求:

public void requestLogin() {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url(url)
            .build();
    client.newCall(request).enqueue(new Callback() {
        Message msg = new Message();
        @Override
        public void onFailure(Call call, IOException e) {
            msg.obj="请求失败";
            handler.sendMessage(msg);
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                if (response.code() == 200) {
                    String result = response.body().string();
                    if(result.equals("SUCCESS LOGIN!")){
                        msg.obj = "授权成功!";
                    }
                }
            }else{
                msg.obj = "出现了未知错误: " + response.code();
            }
            handler.sendMessage(msg);
        }
    });
}

3. 效果:

扫码前,我们直接home;扫码后Ajax处理直接跳转到主页home。
在这里插入图片描述

Demo地址

https://github.com/baiyazi/ScanQrCodeAndAutoLoginDemo

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-08 11:27:20  更:2021-08-08 11:28:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 10:49:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码