008.ASP.NET WEB API 用户注册,登录API

一.简介

本案例使用c# ASP.NET 10编写WEB API网络服务器,通过jwt令牌机制为通过验证的用户签发令牌token,(jwt基础教学见本栏目007篇,SQLite数据库操作见006篇),本节接007优化,

我们的思路是:提供一个公共未加密的用户账号注册api给用户访问,用户访问支api时需用POST网络请求的方式,并向云服务器提供一个我们规定的用户账号Person类对象.属性里有账号和密码等信息,用json格式上传,服务器收到注册请求时,提前申请方的账号去比对数据库中的用户,如果用户名已经存在,拒绝注册,如果不存在,将申请方的账号和密码增加进数据库,注册成功,

用户有了账号密码后就可以访问我们另一支登录api,同样也是post方式请求,并上传用户类对象,服务器会拿申请者的用户名去查找数据库中有无这个用户,如果有,再比对他的密码是否正确,都正确,登录成功,发给他一个jwt令牌token,否则拒绝登录.

拿到的token令牌可以访问到服务器jwt加密的api

二,实现方式

1.建立用户对象模型类Person

cs 复制代码
namespace Esp32_Server.Models
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Power { get; set; }
        public string Email { get; set; }
    }
}

2.封装数据库操作类

见006篇

3.创建用户注册账号类Login.cs

cs 复制代码
using Esp32_Server.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Esp32_Server.Controllers
{


    /// <summary>
    /// 用户注册登录类
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class Login : ControllerBase
    {
        private  List<Person> people; //用户数据库list对象

        //查詢全部新聞
        [HttpGet]
        public IEnumerable<Person> Get()
            {
                people = Linq_table.GetAllPeople(); //查询数据表中全部数据
                return people;
            }
       

        //注册一个账户
        [HttpPost]
        public IActionResult Post(Person value)
        {
            // 1. 先检查内存中是否已存在(可选,作为第一道防线)
            var people = Linq_table.GetAllPeople();//获取数据库中所有用户对象
            if (people.Any(p => p.Name.Trim() == value.Name.Trim()))
            {
                return Conflict(new { message = "名称已存在,请修改。" });
            }

            try
            {
                // 2. 尝试写入数据库
                Linq_table.InsertPerson(value.Name, value.Power, value.Email);
            }
            catch (Exception ex)
            {
   
                // 返回 400 或 409 错误给前端,而不是让程序崩溃
                return BadRequest(new { message = "注册失败,用户名已经存在。" });
            }
           
            //注册成功
            return Ok(Linq_table.GetAllPeople());//查询所有数据库(测试用),实际使用时删除
        }
  

    }
}

4.创建用户登录验证控制器类MemberLogin.cs

注意jwt密匙要设置为和服务器Program.cs配置的jwt密匙一样

cs 复制代码
using Esp32_Server.Administrator;
using Esp32_Server.Controllers;
using Esp32_Server.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Esp32_Server.Member
{
    /// <summary>
    /// 用户登录验证类,传入一个用户类对象,如果数据库有这个用户名,且密码正确,则返回一个JWT令牌
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class MemberLogin : ControllerBase
    {

        private List<Person> people; //用户数据库list对象

        /// <summary>
        /// 登录验证,传入一个用户类对象,如果用户名和密码正确,则返回一个JWT令牌
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public IActionResult Login([FromBody] Person request)
        {
            // 1. 获取数据库中的所有用户
            people = Linq_table.GetAllPeople();

            // 2. 使用 LINQ 的 FirstOrDefault 查找是否存在同名用户
            var user = people.FirstOrDefault(p => p.Name == request.Name);

            // 3. 验证逻辑:
            // 如果 user 为 null,说明没找到;如果找到,再比对密码
            if (user != null && user.Power == request.Power)
            {
                // 验证通过,生成令牌
                var token = GenerateJwtToken(user.Name);
                return Ok(new { token });
            }

            // 4. 用户名不存在或密码错误,统一返回 Unauthorized
            return Unauthorized(new { message = "用户名或密码错误" });
        }

        //生成令牌
        private string GenerateJwtToken(string username)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("服务器设置的jwt秘钥"));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: "yourdomain.com",
                audience: "yourdomain.com",
                claims: new[] { new Claim(ClaimTypes.Name, username) },
                expires: DateTime.Now.AddHours(8),//设置token令牌的有效期为8小时
                signingCredentials: credentials);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}

5.注册测试

服务器用http方式运行,

查询所有数据库的账户信息,这支api实际是管理员的,不允许被其他人访问,后期会删除,

请求方式: GET

URL :http://localhost:5264/api/login

返回:服务器数据库所有用户信息(非常危险,后期不允许这支api被用户访问),他就是Login_GET这支api

我们可以看到,服务器数据库里现在有两个用户对象,现在测试新注册一个用户账号

请求方式:POST

报文Body: Person类格式的json数据

URL : :http://localhost:5264/api/login

可以看到,我们提交的账号密码成功注册,并写进了服务器数据库,至于id为什么是5,这是因为数据库的id是不可以被重复使用的,前面有人用过这个3的id,即使他删除了,数据库也不会去重复使用这些使用过的id

我们故意再注册一次已经存在的这个小红账号,看看服务器会不会成功拒绝我们注册

成功拦截已存在的用户注入

6.登录测试

请求方式:POST

报文Body: Person类格式的json数据

URL : http://localhost:5264/api/MemberLogin

我们提交我们刚刚注册的这个

账号:"小红",

密码;"123456"

发起请求后,服务器拿账号和密码去数据库查找比对,找到了小红这个账号并且密码正确,服务器反馈给我们一个jwt令牌token,它的有限期是8小时,拿着这个token,我们就可以去访问到服务器其他用token加密的api了,

至于怎么访问加密的api, 007篇有基础原理教学,后续章节会出高级的封装用法

相关推荐
FirstFrost --sy1 小时前
基于高并发服务器的web小游戏测试
服务器·前端·javascript·c++·python·集成测试
sbjdhjd2 小时前
Tomcat(下) 集群高可用实战:反向代理・负载均衡・分布式 Session
运维·前端·云原生·开源·tomcat·负载均衡·memcached
xjxijd2 小时前
行为感知算法赋能运维,提前预判硬件故障与异常访问
运维·算法
ai_coder_ai2 小时前
如何使用adb实现自动化脚本?
运维·adb·自动化
Splashtop高性能远程控制软件2 小时前
微软2026年6月补丁星期二技术分析:206个漏洞、3个已公开零日的分级修复方案
运维·安全·自动化·远程桌面·splashtop
陈猪的杰咪2 小时前
【2026最新指南】AI大模型API中转站选型参考:国内稳定接入ChatGPT、Claude、Gemini等主流模型实践分享
运维·网络·人工智能·chatgpt·架构
keyipatience2 小时前
命名管道:跨进程通信的终极指南
linux·运维·服务器
AOwhisky10 小时前
Redis 学习笔记(第三期):持久化与主从复制
运维·数据库·redis·笔记·学习·云计算
c2385610 小时前
Linux C++ 进度条进阶美化与工程化封装
linux·运维·服务器