惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
C
Cisco Blogs
The Hacker News
The Hacker News
T
Threatpost
S
Schneier on Security
K
Kaspersky official blog
Spread Privacy
Spread Privacy
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
NISL@THU
NISL@THU
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Security Latest
Security Latest
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
News and Events Feed by Topic
爱范儿
爱范儿
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News and Events Feed by Topic
V
V2EX
Webroot Blog
Webroot Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
L
LangChain Blog
W
WeLiveSecurity
Cloudbric
Cloudbric

博客园 - SHENHUANJIE

Marvis 使用进阶:联动与外部资源整合 这是一篇用 Marvis发布的文章,让大家都去用 Marvis 程序员保持高效的5个习惯 Kimi WebBridge:让 AI 真正操控你的浏览器 腾讯突然扔出王炸!马维斯一夜刷屏,打工人终于有救了? AIGC-测试库账号密码 openspec 是什么?怎么正确使用? # Hello World 的传奇起源 Please Start Here AI助手记忆系统:从金鱼到大象的进化之路 mac 快速切换 python 版本 卢曼卡片盒笔记法介绍 Introduction to the Zettelkasten Method Uni-app页面信息与元素影响解析 DevOps 入门指南:基础知识解读 「读书计划」《啊哈!算法》7日结构化学习规划 Java RestTemplate 发送 POST 请求设置请求体示例 跨平台开发方案:优缺点对比及选择指南 Java实现简单多层感知器神经网络 Google开发者账号注册步骤详解 ipify.org:免费IP查询服务详解 Google开发者利器:云平台与Firebase服务解析 Google Fonts字体库使用指南 UNI-APP 获取用户手机号授权与服务器端处理指南 MySQL 8.0 如何禁用 ONLY_FULL_GROUP_BY 平衡工作与生活的10个实用方法 Linux安装Ollama并启用服务教程 如何在 LobeChat 中使用 Ollama Deprecation Warning: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
UNI-APP + Spring Boot 实现小程序手机号登录
SHENHUANJIE · 2025-01-15 · via 博客园 - SHENHUANJIE

  以下是整合后的完整方案,结合了 UNI-APP 前端Java Spring Boot 后端,实现小程序手机号登录功能:

1. 前端实现:获取用户手机号并调用登录接口

  在 UNI-APP 中,使用 button​ 组件获取用户的手机号授权,并将授权后的 code​ 发送到后端登录接口。

1.1 前端代码

<template>
  <view>
    <button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">手机号登录</button>
  </view>
</template>

<script>
export default {
  methods: {
    async getPhoneNumber(e) {
      if (e.detail.errMsg === 'getPhoneNumber:ok') {
        // 用户点击了允许授权
        const { code } = e.detail;

        // 调用后端登录接口
        const res = await uni.request({
          url: 'https://your-server.com/api/loginByPhone', // 替换为你的后端地址
          method: 'POST',
          data: { code },
        });

        if (res.data.success) {
          // 登录成功,保存用户信息和 token
          uni.setStorageSync('userInfo', res.data.data.user);
          uni.setStorageSync('token', res.data.data.token);
          uni.showToast({ title: '登录成功', icon: 'success' });
          uni.navigateTo({ url: '/pages/home/index' }); // 跳转到首页
        } else {
          uni.showToast({ title: '登录失败', icon: 'none' });
        }
      } else {
        // 用户点击了拒绝授权
        uni.showToast({ title: '用户拒绝授权', icon: 'none' });
      }
    }
  }
}
</script>

2. 后端实现:Spring Boot 处理登录逻辑

  后端需要完成以下任务:

  1. 通过 code​ 获取用户的手机号。
  2. 根据手机号查询用户是否存在。
  3. 如果用户不存在,则创建新用户。
  4. 返回用户信息和登录凭证(如 token​)。

2.1 添加依赖

  在 pom.xml​ 中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

2.2 配置微信小程序信息

  在 application.properties​ 中配置微信小程序的 appid​ 和 secret​:

wechat.appid=YOUR_APPID
wechat.secret=YOUR_APPSECRET

2.3 实现获取 access_token​ 和手机号

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class WechatService {

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.secret}")
    private String secret;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 获取 access_token
    public String getAccessToken() throws Exception {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(url);
            String response = EntityUtils.toString(httpClient.execute(request).getEntity());
            JsonNode jsonNode = objectMapper.readTree(response);
            return jsonNode.get("access_token").asText();
        }
    }

    // 获取用户手机号
    public String getPhoneNumber(String code) throws Exception {
        String accessToken = getAccessToken();
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost request = new HttpPost(url);
            request.setHeader("Content-Type", "application/json");
            String jsonBody = "{\"code\":\"" + code + "\"}";
            request.setEntity(new StringEntity(jsonBody));

            String response = EntityUtils.toString(httpClient.execute(request).getEntity());
            JsonNode jsonNode = objectMapper.readTree(response);
            return jsonNode.path("phone_info").path("phoneNumber").asText();
        }
    }
}

2.4 实现登录逻辑

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class LoginController {

    @Autowired
    private WechatService wechatService;

    @Autowired
    private UserService userService;

    @PostMapping("/api/loginByPhone")
    public ApiResponse loginByPhone(@RequestBody LoginRequest request) throws Exception {
        String code = request.getCode();
        String phoneNumber = wechatService.getPhoneNumber(code);

        // 查询用户是否存在
        User user = userService.findUserByPhoneNumber(phoneNumber);
        if (user == null) {
            // 如果用户不存在,创建新用户
            user = userService.createUser(phoneNumber);
        }

        // 生成 token(这里简单模拟)
        String token = "token_" + user.getUserId();

        // 返回用户信息和 token
        return new ApiResponse(true, "登录成功", new LoginResponse(user, token));
    }
}

// 用户实体类
class User {
    private String userId;
    private String phoneNumber;

    // Getters and Setters
}

// 用户服务类
@Service
class UserService {
    private final List<User> users = new ArrayList<>();

    public User findUserByPhoneNumber(String phoneNumber) {
        return users.stream()
                .filter(user -> user.getPhoneNumber().equals(phoneNumber))
                .findFirst()
                .orElse(null);
    }

    public User createUser(String phoneNumber) {
        User user = new User();
        user.setUserId(String.valueOf(System.currentTimeMillis()));
        user.setPhoneNumber(phoneNumber);
        users.add(user);
        return user;
    }
}

// 请求和响应类
class LoginRequest {
    private String code;

    // Getters and Setters
}

class LoginResponse {
    private User user;
    private String token;

    // Getters and Setters
}

class ApiResponse {
    private boolean success;
    private String message;
    private Object data;

    // Getters and Setters
}

3. 安全性注意事项

  1. code的有效性:确保 code​ 是一次性的,且及时使用。
  2. access_token缓存:避免频繁请求微信 API,缓存 access_token​。
  3. HTTPS:确保接口使用 HTTPS 加密传输。
  4. 用户隐私:手机号是敏感信息,确保存储和传输过程中加密。

4. 总结

  通过以上步骤,你可以实现以下功能:

  1. 前端获取用户手机号授权,发送 code​ 到后端。
  2. 后端通过 code​ 获取手机号,完成登录逻辑。
  3. 前端保存登录状态,并在需要时校验登录状态。

  这种方案既符合微信小程序的规范,又能满足常见的登录需求。