.net core web项目teachers表的CRUD和基于JWT的登录登出以及给接口添加权限控制

(1)导入Pomelo.EntityFrameworkCore.Mysql

(2)导入Swashbuckle.AspNetCore

(3)导入Microsoft.AspNetCore.Authentication.JwtBearer

一.前期配置

1.Startup.cs

using CRUD4.Models;
using CRUD4.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Security.Claims;
using System.Security.Cryptography;

namespace CRUD4
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            // Add your services here
            string connectionString = Configuration.GetConnectionString("DefaultConnection");
            services.AddScoped<ITeacherRepository, TeacherRepository>();
            services.AddScoped<ITeacherService, TeacherService>();
            services.AddScoped<RsaSecurityKey>();
            services.AddHttpContextAccessor();
            services.AddScoped<ITokenBlacklistService, TokenBlacklistService>();
            services.AddLogging();


            //swager
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" });
            });

            //database
            services.AddDbContext<MyContext>(options =>
                options.UseMySql
                (connectionString, ServerVersion.AutoDetect(connectionString))
                );

            // 生成 RSA 密钥对
            RSA rsa = RSA.Create(2048);
            var privateKey = rsa;
            var publicKey = rsa.ExportRSAPublicKey();

            // 将密钥保存到服务中,以便后续使用
            services.AddSingleton(privateKey);
            services.AddSingleton(publicKey);

            // 配置 JWT 认证
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new RsaSecurityKey(privateKey)
                    };
                    options.Events = new JwtBearerEvents
                    {
                        OnTokenValidated = async context =>
                        {
                            var blacklistService = context.HttpContext.RequestServices.GetRequiredService<ITokenBlacklistService>();
                            var token = context.Request.Headers["Authorization"].ToString();
                            if (token != null && await blacklistService.IsBlacklisted(token.Substring(7)))
                            {
                                context.Fail("This token is blacklisted");
                            }
                        }
                    };
                });
            //添加自定义接口访问权限   在接口上加[Authorize(Policy = "admin")]
            services.AddAuthorization(options =>
            {
                options.AddPolicy("admin", policy =>
                {
                    policy.RequireAuthenticatedUser(); // 用户必须经过身份验证
                    policy.RequireClaim(ClaimTypes.Name, "T2024002"); // 用户必须具有指定的声明(即指定的信息为""里的信息)
                });
            });


        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();

                app.UseSwagger();
                // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
                // specifying the Swagger JSON endpoint.
                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "Your API V1");
                });
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            //添加身份验证中间件
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

2.Program.cs

namespace CRUD4;
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

3.appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=demo1;User=root;Password=123456;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

4.统一返回类R

namespace CRUD4.Commons
{
    public class R<T>
    {
        public int Code { get; set; } // 编码:1成功,0和其它数字为失败

        public string Msg { get; set; } // 错误信息

        public T Data { get; set; } // 数据

        public Dictionary<string, object> Map { get; set; } = new Dictionary<string, object>(); // 动态数据

        public static R<T> Success(T data)
        {
            return new R<T> { Data = data, Code = 1 };
        }

        public static R<T> Error(string msg)
        {
            return new R<T> { Msg = msg, Code = 0 };
        }

        public R<T> Add(string key, object value)
        {
            this.Map[key] = value;
            return this;
        }
    }
}

二.模型文件夹

1.数据库配置

using Microsoft.EntityFrameworkCore;

namespace CRUD4.Models
{
    public class MyContext : DbContext
    {
        public DbSet<Teacher> Teachers { get; set; }

        public DbSet<Course> Courses { get; set; }

        public MyContext(DbContextOptions<MyContext> options)
        :base(options)
        {
        }
    }
}

2.Teacher类

namespace CRUD4.Models
{
    public class Teacher
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Code { get; set; }
        public string Password { get; set; }
    }
}

3.TeacherLocalModel类

用于教师登录操作,使用Code教师编号和Password登录

namespace CRUD4.Models
{
    public class TeacherLoginModel
    {
        public string Code{  get; set; }
        public string Password { get; set; }
    }
}

4.ITeacherRepository

namespace CRUD4.Models
{
    public interface ITeacherRepository
    {
        void AddTeacher(Teacher teacher);
        void RemoveTeacherByCode(string code);
        void UpdateTeacher(Teacher teacher);
        Teacher GetTeacherById(int id);
        IEnumerable<Teacher> GetTeacherByName(string name);
        Teacher GetTeacherByCode(string code);
        IEnumerable<Teacher> GetAllTeachers();

        Teacher Login(TeacherLoginModel teacherLoginModel);
    }
}

5.TeacherRepository


namespace CRUD4.Models
{
    public class TeacherRepository : ITeacherRepository
    {

        private readonly MyContext _context;
        public TeacherRepository(MyContext context) {
        _context = context;
        }
        public void AddTeacher(Teacher teacher)
        {
            _context.Teachers.Add(teacher);
            _context.SaveChanges();
        }
        public void RemoveTeacherByCode(string code)
        {
            var teacher=_context.Teachers.FirstOrDefault(t=>t.Code == code);
            _context.Teachers.Remove(teacher);
            _context.SaveChanges(true);
        }

        public void UpdateTeacher(Teacher teacher)
        {
            var teacher1=_context.Teachers.FirstOrDefault(t=>t.Id == teacher.Id );
            _context.Teachers.Entry(teacher1).CurrentValues.SetValues(teacher);
            _context.SaveChanges();
        }
        public IEnumerable<Teacher> GetAllTeachers()
        {
            return _context.Teachers.ToList();
        }

        public Teacher GetTeacherByCode(string code)
        {
            return _context.Teachers.FirstOrDefault(t => t.Code == code);
        }

        public Teacher GetTeacherById(int id)
        {
            return _context.Teachers.FirstOrDefault(t => t.Id == id);
        }

        public IEnumerable<Teacher> GetTeacherByName(string name)
        {
            return _context.Teachers.Where(t => t.Name.Contains(name)).ToList();
        }

        public Teacher Login(TeacherLoginModel teacherLoginModel)
        {
            return _context.Teachers.FirstOrDefault(t => t.Code == teacherLoginModel.Code && t.Password == teacherLoginModel.Password);
        }
    }
}

6.ITokenBlacklistService

用于退出功能把token拉进黑名单

namespace CRUD4.Models
{
    public interface ITokenBlacklistService
    {
        Task<bool> IsBlacklisted(string token);
        Task AddTokenToBlacklist(string token);
    }
}

7.TokenBlacklistService

namespace CRUD4.Models
{
    public class TokenBlacklistService : ITokenBlacklistService
    {
        // 这里假设黑名单存储在内存中的集合中,您可以根据实际需求将其替换为数据库或其他持久化存储方式
        private readonly HashSet<string> _blacklistedTokens;

        public TokenBlacklistService()
        {
            _blacklistedTokens = new HashSet<string>();
        }

        public Task<bool> IsBlacklisted(string token)
        {
            // 模拟异步操作
            return Task.FromResult(_blacklistedTokens.Contains(token));
        }

        public Task AddTokenToBlacklist(string token)
        {

            // 去掉 "Bearer " 前缀
            var tokenValue = token.Substring("Bearer ".Length);
            // 模拟异步操作
            _blacklistedTokens.Add(tokenValue);
            return Task.CompletedTask;
        }
    }
}

三.Service层

1.ITeacherService

using CRUD4.Commons;
using CRUD4.Models;

namespace CRUD4.Services
{
    public interface ITeacherService
    {
        R<string> AddTeacher(Teacher teacher);
        R<string> DeleteTeacher(string code);
        R<string> UpdateTeacher(Teacher teacher);
        R<Teacher> GetTeacherById(int id);
        R<IEnumerable<Teacher>> GetTeacherByName(string name);
        R<Teacher> GetTeacherByCode(string code);
        R<IEnumerable<Teacher>> GetAllTeachers();
        R<string> Login(TeacherLoginModel teacherLoginModel);
        R<string> Logout();
    }
}

2.TeacherService

using CRUD4.Commons;
using CRUD4.Models;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace CRUD4.Services
{
    public class TeacherService : ITeacherService
    {
        private readonly ITeacherRepository _repository;
        private readonly RsaSecurityKey _securityKey;
        private readonly IDictionary<string, string> _tokens;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ITokenBlacklistService _tokenBlacklistService;
        private readonly ILogger<TeacherService> _logger;
        public TeacherService(ITeacherRepository repository,RsaSecurityKey securityKey,
            IHttpContextAccessor httpContextAccessor,
            ILogger<TeacherService> logger,
            ITokenBlacklistService tokenBlacklistService)
        {
            _repository = repository;
            _securityKey = securityKey;
            _tokens = new Dictionary<string, string>();
            _httpContextAccessor = httpContextAccessor;
            _logger = logger;
            _tokenBlacklistService = tokenBlacklistService;
        }
        public R<string> AddTeacher(Teacher teacher)
        {
            var teacher1=_repository.GetTeacherByCode(teacher.Code);
            if(teacher1 == null)
            {
                _repository.AddTeacher(teacher);
                return R<string>.Success("新增成功");
            }
            return R<string>.Error("新增失败");
        }

        public R<string> DeleteTeacher(string code)
        {
            var teacher=_repository.GetTeacherByCode(code);
            if(teacher != null)
            {
                _repository.RemoveTeacherByCode(code);
                return R<string>.Success("删除成功");
            }
            return R<string>.Error("删除失败,没有此编号的老师");
        }
        public R<string> UpdateTeacher(Teacher teacher)
        {
            var teacher1 = _repository.GetTeacherById(teacher.Id);
            if(teacher1 != null)
            {
                _repository.UpdateTeacher(teacher);
                return R<string>.Success("修改成功");
            }
            return R<string>.Error("修改失败,没有此编号的老师");
        }

        public R<IEnumerable<Teacher>> GetAllTeachers()
        {
            return R<IEnumerable<Teacher>>.Success(_repository.GetAllTeachers());
        }

        public R<Teacher> GetTeacherByCode(string code)
        {
            var teacher = _repository.GetTeacherByCode(code);
            if (teacher != null)
            {
                return R<Teacher>.Success(teacher);
            }
            return R<Teacher>.Error("没有这个编号的老师");
        }

        public R<Teacher> GetTeacherById(int id)
        {
            var teacher = _repository.GetTeacherById(id);
            if (teacher != null)
            {
                return R<Teacher>.Success(teacher);
            }
            return R<Teacher>.Error("没有这个id的老师");
        }

        public R<IEnumerable<Teacher>> GetTeacherByName(string name)
        {
            var teacher = _repository.GetTeacherByName(name);
            if (teacher != null)
            {
                return R<IEnumerable<Teacher>>.Success(teacher);
            }
            return R<IEnumerable<Teacher>>.Error("没有这个名字的老师");
        }

        public R<string> Login(TeacherLoginModel teacherLoginModel)
        {
            var teacher=_repository.Login(teacherLoginModel);
            if(teacher != null)
            {
                var token = GenerateToken(teacher.Code);
                // 登录成功后将 Teacher 对象存储在 HttpContext.Items 中
                //_contextAccessor.HttpContext.Items["LoggedInTeacher"] = teacher;
                return R<string>.Success(token);
            }
            return R<string>.Error("登录失败");
        }
        /*
        public R<string> Logout()
        {

            if (_contextAccessor.HttpContext.Items.ContainsKey("LoggedInTeacher"))
            {
                var teacher = (Teacher)_contextAccessor.HttpContext.Items["LoggedInTeacher"];
                ClearToken(teacher.Code);
                return R<string>.Success("退出成功");
            }
            else
            {
                return R<string>.Error("退出失败,必须先登录才能退出");
            }
        }
        */

        public  R<string> Logout()
        {

            if (_httpContextAccessor == null || _tokenBlacklistService == null)
            {
                _logger.LogError("HttpContextAccessor or TokenBlacklistService is null.");
                return R<string>.Error("服务未正确配置");
            }
            var token = _httpContextAccessor.HttpContext.Request.Headers["Authorization"].FirstOrDefault();
            if(token == null|| !token.StartsWith("Bearer "))
            {
                return R<string>.Error("退出失败");
            }

            // 去掉 "Bearer " 前缀
            var tokenValue = token.Substring("Bearer ".Length);

            // 调用添加到黑名单的方法
            _tokenBlacklistService.AddTokenToBlacklist(tokenValue);

            return R<string>.Success("退出成功");
        }
        public string GenerateToken(string tcode)
        {
            var signingCredentials = new SigningCredentials(_securityKey, SecurityAlgorithms.RsaSha256);
            var claims = new[ ]
            {
                new Claim(ClaimTypes.Name,tcode)
        };
            var jwt=new JwtSecurityToken(
                claims:claims, 
                signingCredentials:signingCredentials,
                expires:DateTime.UtcNow.AddMinutes(30));
            var token =new JwtSecurityTokenHandler().WriteToken(jwt);
            return token;
        }

        public void ClearToken(string tcode)
        {
            if (_tokens.ContainsKey(tcode))
            {
                _tokens.Remove(tcode);            
            }
        }
    }
}

四.控制器层

1.TeacherController

using CRUD4.Models;
using CRUD4.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace CRUD4.Controllers
{
    [ApiController]
    [Route("api/teacher")]
    public class TeacherController : Controller
    {
        private readonly ITeacherService _service;

        public TeacherController(ITeacherService service)
        {
            _service = service;
        }

        //Post: api/teacher/add
        [HttpPost("add")]
        public IActionResult AddTeacher(Teacher teacher)
        {
            return Ok(_service.AddTeacher(teacher));
        }

        //Delete: api/teacher/delete/T2024003
        [HttpDelete("delete/{code}")]
        public IActionResult DeleTeacher(string code)
        {
            return Ok(_service.DeleteTeacher(code));
        }

        //Post: api/teacher/update
        [HttpPost("update")]
        public IActionResult UpdateTeacher(Teacher teacher)
        {
            return Ok(_service.UpdateTeacher(teacher));
        }

        //Get: api/teacher/1
        [HttpGet("{id}")]
        public IActionResult GetTeacherById(int id)
        {
            return Ok(_service.GetTeacherById(id));
        }

        //Get: api/teacher/getByCode/T2024001
        [HttpGet("getByCode/{code}")]
        public IActionResult GetTeacherByCode(string code)
        {
            return Ok(_service.GetTeacherByCode(code));
        }

        //Get: api/teacher/getByName/李老师
        [HttpGet("getByName/{name}")]
        public IActionResult GetTeacherByName(string name)
        {
            return Ok(_service.GetTeacherByName(name));
        }

        //Get: api/teacher
        [HttpGet]
        [Authorize(Policy ="admin")]
        public IActionResult GetAllTeachers()
        {
            return Ok(_service.GetAllTeachers());
        }

        //Post: api/teacher/login
        [HttpPost("login")]
        public IActionResult Login(TeacherLoginModel teacherLoginModel)
        {
            return Ok(_service.Login(teacherLoginModel));
        }

        //Post: api/teacher/logout
        [HttpPost("logout")]
        [Authorize]
        public IActionResult Logout()
        {
            return Ok(_service.Logout());
        }

        [HttpGet("index")]
        public IActionResult Index()
        {
            return View();
        }
    }
}


 

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值