【Spring AI】基于专属知识库的RAG智能问答小程序开发——功能优化:用户鉴权

系列文章目录

  1. 【Spring AI】基于专属知识库的RAG智能问答小程序开发------完整项目(含完整前端+后端代码)
  2. 【Spring AI】基于专属知识库的RAG智能问答小程序开发------代码逐行精讲:核心ChatClient对象相关构造函数
  3. 【Spring AI】基于专属知识库的RAG智能问答小程序开发------代码逐行精讲:核心交互函数及RAG知识库构建
  4. 【Spring AI】基于专属知识库的RAG智能问答小程序开发------功能优化:用户鉴权主体功能开发

文章目录


前言

在前几篇文章中,我们不仅成功搭建了一个具备知识检索与生成能力的AI问答系统,实现了从知识库构建、向量化存储到微信端交互的完整链路。还通过代码逐行精讲阐明了后端开发中SpringAI框架的使用方法和相关参数含义。

显而易见地,一个成熟的AI问答助手需要对用户鉴权,从而保证用户身份的真实性和请求的合法性。通过对用户鉴权我们就能够限定用户发送的请求数,从而避免api的恶意攻击和消耗。因此,本文主要通过编写后端中的SpringBoot代码实现用户鉴权逻辑,前端则主要使用wx.login函数获取用户的code后进一步获取openid,最终实现身份认证。

1.开发工具及环境准备

1.1.开发工具

IntelliJ IDEA

微信开发者工具

MySQL

JDK版本 >= 17

Spring Boot版本 >= 3.3.x

阿里云百炼api_keyu获取:阿里云百炼官网api获取教程

1.2.数据库准备

1.2.1.数据表构建命令

sql 复制代码
CREATE TABLE user (
                       id INT AUTO_INCREMENT PRIMARY KEY,
                       openid VARCHAR(50) NOT NULL UNIQUE,
                       res_request INT NOT NULL DEFAULT 5
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

1.2.2.数据表构建效果

2.后端代码-登录鉴权

2.1.SpringBoot文件架构:

2.2.SpringBoot核心文件代码:

2.2.1.UserController代码:主要用于定义Controller层逻辑,接收和返回网络请求

java 复制代码
package com.alichat.alibabaChatModel.controller;

import com.alichat.alibabaChatModel.DTO.UserLoginDTO;
import com.alichat.alibabaChatModel.VO.UserLoginVO;
import com.alichat.alibabaChatModel.constant.JwtClaimsConstant;
import com.alichat.alibabaChatModel.entity.User;
import com.alichat.alibabaChatModel.properties.JwtProperties;
import com.alichat.alibabaChatModel.result.Result;
import com.alichat.alibabaChatModel.service.UserService;
import com.alichat.alibabaChatModel.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 用户管理
 */

@RestController
@RequestMapping("/ali/user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 微信登录
     * @param userLoginDTO
     * @return
     */
    @PostMapping("/login")
    public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
        log.info("微信登录:{}", userLoginDTO.getCode());

        User user = userService.wxlogin(userLoginDTO);
        HashMap<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);

        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .openid(user.getOpenid())
                .token(token)
                .build();
        log.info(userLoginVO.getToken());
        return Result.success(userLoginVO);
    }

}

2.2.2.UserService代码:主要用于定义Service层接口

java 复制代码
package com.alichat.alibabaChatModel.service;

import com.alichat.alibabaChatModel.DTO.UserLoginDTO;
import com.alichat.alibabaChatModel.entity.User;

public interface UserService {

    /**
     * 微信登录
     * @param userLoginDTO
     * @return
     */
    User wxlogin(UserLoginDTO userLoginDTO);

    /**
     * 根据用户id查询用户
     * @param id
     * @return
     */
    User getById(Long id);

    /**
     * 更新用户
     * @param user
     * @return
     */
    void updateUser(User user);
}

2.2.3.UserServiceImpl代码:主要用于定义Service层的具体逻辑实现

java 复制代码
package com.alichat.alibabaChatModel.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alichat.alibabaChatModel.DTO.UserLoginDTO;
import com.alichat.alibabaChatModel.constant.MessageConstant;
import com.alichat.alibabaChatModel.entity.User;
import com.alichat.alibabaChatModel.exception.AccountNotFoundException;
import com.alichat.alibabaChatModel.exception.LoginFailedException;
import com.alichat.alibabaChatModel.exception.PasswordErrorException;
import com.alichat.alibabaChatModel.mapper.UserMapper;
import com.alichat.alibabaChatModel.properties.WeChatProperties;
import com.alichat.alibabaChatModel.service.UserService;
import com.alichat.alibabaChatModel.utils.HttpClientUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    //微信服务接口地址
    public static final String WX_LOGIN = "http://api.weixin.qq.com/sns/jscode2session";

    @Autowired
    private WeChatProperties weChatProperties;

    @Autowired
    UserMapper userMapper;

    /**
     * 调用微信接口服务,获取微信用户的openid
     * @param code
     * @return
     */
    private String getOpenid(String code) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("appid", weChatProperties.getAppid());
        map.put("secret", weChatProperties.getSecret());
        map.put("js_code", code);
        map.put("grant_type", "authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN, map);
        JSONObject jsonObject = JSON.parseObject(json);
        String openid = jsonObject.getString("openid");
        return openid;
    }

    /**
     * 微信登录
     * @param userLoginDTO
     * @return
     */
    public User wxlogin(UserLoginDTO userLoginDTO) {
        String openid = getOpenid(userLoginDTO.getCode());
        if(openid == null) {
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }

        User user = userMapper.getByOpenid(openid);
        long resRequset = 5;
        if(user == null) {
            user = User.builder()
                    .openid(openid)
                    .resRequest(resRequset)
                    .build();
            userMapper.insert(user);
        }
        return user;
    }

    /**
     * 根据用户id查询用户
     * @param id
     * @return
     */
    public User getById(Long id){
        User user = userMapper.getById(id);
        return user;
    }

    /**
     * 更新用户
     * @param user
     * @return
     */
    public void updateUser(User user){
        userMapper.update(user);
    }
}

2.2.4.UserMapper代码:主要用于定义Mapper层的接口以及具体实现

代码主要分为两个同名文件,java文件位于com.alichat.alibabaChatModel的mapper文件夹下,xml文件位于resources的mapper文件夹下,这两个文件时对应的。

UserMapper.java文件代码:

java 复制代码
package com.alichat.alibabaChatModel.mapper;

import com.alichat.alibabaChatModel.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {
    /**
     * 根据openid获取用户
     * @param openid
     * @return
     */
    @Select("select * from user where openid = #{openid}")
    User getByOpenid(String openid);

    /**
     * 插入用户
     * @param user
     */
    void insert(User user);

    /**
     * 根据id获取用户
     * @param id
     * @return
     */
    @Select("select * from user where id = #{id}")
    User getById(Long id);

    /**
     * 更新用户
     * @param user
     * @return
     */
    void update(User user);
}

UserMapper.xml文件代码:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.alichat.alibabaChatModel.mapper.UserMapper">
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        insert into user (openid, res_request)
        values (#{openid},#{resRequest})
    </insert>
    <update id="update">
        update user
        <set>
            <if test="openid != null">openid = #{openid},</if>
            <if test="resRequest != null">res_request = #{resRequest},</if>
        </set>
        where id = #{id}
    </update>
</mapper>
相关推荐
alden_ygq10 分钟前
当java进程内存使用超过jvm设置大小会发生什么?
java·开发语言·jvm
triticale24 分钟前
【Java】网络编程(Socket)
java·网络·socket
kovlistudio25 分钟前
机器学习第三讲:监督学习 → 带答案的学习册,如预测房价时需要历史价格数据
人工智能·机器学习
淘源码d27 分钟前
什么是ERP?ERP有哪些功能?小微企业ERP系统源码,SpringBoot+Vue+ElementUI+UniAPP
java·源码·erp·erp源码·企业资源计划·企业erp·工厂erp
源码方舟28 分钟前
【基于ALS模型的教育视频推荐系统(Java实现)】
java·python·算法·音视频
嵌入式仿真实验教学平台29 分钟前
「国产嵌入式仿真平台:高精度虚实融合如何终结Proteus时代?」——从教学实验到低空经济,揭秘新一代AI赋能的产业级教学工具
人工智能·学习·proteus·无人机·低空经济·嵌入式仿真·实验教学
Mcworld8571 小时前
整数分解JAVA
java·开发语言
正在走向自律1 小时前
Python 数据分析与可视化:开启数据洞察之旅(5/10)
开发语言·人工智能·python·数据挖掘·数据分析
LuvMyLife1 小时前
基于Win在VSCode部署运行OpenVINO模型
人工智能·深度学习·计算机视觉·openvino
fancy1661661 小时前
力扣top100 矩阵置零
人工智能·算法·矩阵