马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、Session+token根本demo
【需求】
Home/Index 登录界面,校验乐成后可以登录到Main/Index ,用户登录3分钟内关闭网站,再次访问Home/Index时可以免密登录Main/Index
【设置文件-Program.cs】- var builder = WebApplication.CreateBuilder(args);
- // Add services to the container.
- builder.Services.AddControllersWithViews();
- //加一个session
- builder.Services.AddSession(options =>
- {
- options.IdleTimeout = TimeSpan.FromMinutes(3); // 3分钟过期
- options.Cookie.HttpOnly = true;
- options.Cookie.IsEssential = true;
- });
- var app = builder.Build();
- // Configure the HTTP request pipeline.
- if (!app.Environment.IsDevelopment())
- {
- app.UseExceptionHandler("/Home/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
- app.UseHttpsRedirection();
- app.UseStaticFiles();
- app.UseRouting();
- app.UseAuthorization();
- //使用session
- app.UseSession();
- app.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
- app.Run();
复制代码 【实现-后端HomeController】- using Microsoft.AspNetCore.Mvc;
- namespace WebApplication1.Controllers
- {
- public class HomeController : Controller
- {
- public IActionResult Index()
- {
- return View();
- }
- [HttpPost]
- public IActionResult Login(string username, string password)
- {
- if (username == "1" && password == "100")//省略数据库读取步骤,假设校验成功了
- {
- CreateToken(HttpContext);//设置token
- return RedirectToAction("Index", "Main");//重定向到已登录界面
- }
- ViewBag.ErrorMessage = "登录失败,账密错误";
- return View("Index");//否则重定向到本页
- }
- private const string TokenSessionKey = "AuthToken";
- private const string TokenExpiryKey = "TokenExpiry";
- public static void CreateToken(HttpContext context)//创建token
- {
- var token = Guid.NewGuid().ToString();//设置token
- var expiry = DateTime.Now.AddMinutes(3);//设置过期日期
- context.Session.SetString(TokenSessionKey, token);
- context.Session.SetString(TokenExpiryKey, expiry.ToString("o")); // 使用 ISO 8601 格式
- }
- }
- }
复制代码 【实现-后端MainController】- using Microsoft.AspNetCore.Mvc;
- namespace WebApplication1.Controllers
- {
- public class MainController : Controller
- {
- public IActionResult Index()
- {
- if (!ValidateToken(HttpContext))//判断是否携带有效token
- {
- return RedirectToAction("Index", "Home");//不是则重定向到登录界面
- }
- return View();//否则重定向到本页(已登录页面)
- }
- private const string TokenSessionKey = "AuthToken";
- private const string TokenExpiryKey = "TokenExpiry";
- public static bool ValidateToken(HttpContext context)
- {
- var token = context.Session.GetString(TokenSessionKey);//尝试获取token
- var expiryString = context.Session.GetString(TokenExpiryKey);//尝试获取过期日期
- if (token == null || expiryString == null)
- {
- return false;//获取不到表明不是登陆状态
- }
- var expiry = DateTime.Parse(expiryString, null, System.Globalization.DateTimeStyles.RoundtripKind);//使用 ISO 8601 格式解析日期
- return DateTime.Now <= expiry;//判断是否过期,如果过期返回false
- }
- }
- }
复制代码 【前端-Home/Index】登录界面- @{
- ViewData["Title"] = "Home";
- }
- <h1>Login</h1>
- <form method="post" action="/Home/Login">
- <div>
- <label for="username">Username:</label>
- <input type="text" id="username" name="username" required />
- </div>
- <div>
- <label for="password">Password:</label>
- <input type="password" id="password" name="password" required />
- </div>
- <button type="submit">Login</button>
- </form>
- @if (ViewBag.ErrorMessage != null)
- {
- <p style="color:red;">@ViewBag.ErrorMessage</p>
- }
复制代码 【小结】
1.HttpContext是当前 HTTP 哀求的上下文信息,它提供了有关哀求和相应的各种数据和服务。
2.以上demo写法不查数据库,不封装AuthService 服务类,仅为展示根本的逻辑
3.前后端交互须要对应控制器名称、控制器下的方法名称
4.利用 ISO 8601 格式(比方 "o")来存储日期时间值,是为了确保日期时间的尺度化和划一性
5.token 举行免登录时,须要后端管理或存储 token,方法有二:
- 一是服务器或redis存储token
- 二是利用JWT将用户信息+逾期时间嵌入 token 中,后端可以验证 token 的有用性从而获取用户id等信息,而不须要存储 token 自己。
拓展
Q:如果须要增长注销功能,应该怎样实现?
A :Main/Index加一个注销按钮,MainController扫除token和逾期时间即可
后端:- // 触发注销方法
- public IActionResult Logout()
- {
- HttpContext.Session.Remove(TokenSessionKey); // 清除 token
- HttpContext.Session.Remove(TokenExpiryKey); // 清除过期时间
- return RedirectToAction("Index", "Home"); // 注销后重定向到主页
- }
复制代码 前端: - <button onclick="logout()">Logout</button> <!-- 注销按钮 -->
- <script>
- function logout() {
- fetch('/Main/Logout', { // 调用后端的 Logout 方法
- method: 'POST', // 使用 POST 请求
- headers: {
- 'Content-Type': 'application/json'
- },
- credentials: 'same-origin' // 确保发送会话 cookie
- })
- .then(response => {
- if (response.ok) {
- window.location.href = '/Home/Index'; // 注销成功后重定向到主页
- } else {
- console.error('Logout failed');
- }
- })
- .catch(error => console.error('Error:', error));
- }
- </script>
复制代码 二、JWT令牌根本demo
【需求】(同上)
Home/Index 登录界面,校验乐成后可以登录到Main/Index ,用户登录3分钟内关闭网站,再次访问Home/Index时可以免密登录Main/Index。
【Home】- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.IdentityModel.Tokens;
- using System.IdentityModel.Tokens.Jwt;
- using System.Security.Claims;
- using System.Text;
- public class HomeController : Controller
- {
- private readonly IConfiguration _configuration;
- private readonly string _jwtSecret ;
- public HomeController(IConfiguration configuration)
- {
- _configuration = configuration;
- _jwtSecret = _configuration.GetConnectionString("DefaultConnection");
- }
- public IActionResult Index()
- {
- return View();
- }
- [HttpPost]
- public IActionResult Index(string username, string password)
- {
- if (username == "1" && password == "100")// 这里应进行实际的用户验证
- {
- var token = GenerateJwtToken(username);//生成JWT令牌
- Response.Cookies.Append("AuthToken", token, new CookieOptions//将生成的 JWT 存储在浏览器的 Cookie 中,设置 HttpOnly 选项可以防止客户端 JavaScript 访问 Cookie,提高安全性。
- {
- HttpOnly = true,
- Expires = DateTime.UtcNow.AddMinutes(3) //过期时间3分钟
- });
- return RedirectToAction("Index", "Main");
- }
- ViewBag.ErrorMessage = "登陆失败";
- return View("Index");
- }
- private string GenerateJwtToken(string username)
- {
- var tokenHandler = new JwtSecurityTokenHandler();
- var key = Encoding.ASCII.GetBytes(_jwtSecret);//密钥,用于签名 JWT
- var tokenDescriptor = new SecurityTokenDescriptor
- {
- Subject = new ClaimsIdentity(new Claim[]
- {
- new Claim(ClaimTypes.Name, username),//// 设置 JWT 的声明部分,包含用户信息。在这里,我们只设置了用户名
- // 你可以添加更多的声明,如角色、权限等
- new Claim(ClaimTypes.Role, "admin") // 示例,添加用户角色
- }),
- Expires = DateTime.UtcNow.AddMinutes(3),//过期时间为3分钟
- SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)//设置 JWT 的签名凭据。SigningCredentials 包含签名的密钥和算法,使用 HMAC-SHA256 算法进行签名
- };
- var token = tokenHandler.CreateToken(tokenDescriptor);
- return tokenHandler.WriteToken(token);// 生成并且返回 JWT 字符串
- }
- }
复制代码 【Main】- using Microsoft.AspNetCore.Mvc;
- using Microsoft.IdentityModel.Tokens;
- using System.IdentityModel.Tokens.Jwt;
- using System.Security.Claims;
- using System.Text;
- public class MainController : Controller
- {
- private readonly IConfiguration _configuration;
- private readonly string _jwtSecret;
- public MainController(IConfiguration configuration)
- {
- _configuration = configuration;
- _jwtSecret = _configuration.GetConnectionString("DefaultConnection");
- }
- public IActionResult Index()
- {
- var token = Request.Cookies["AuthToken"];//从 Cookie 中读取 JWT(Key设置成了 "AuthToken",读取它的值token)。
- if (ValidateToken(token))//校验token
- {
- return View();
- }
- return RedirectToAction("Index", "Home");
- }
- private bool ValidateToken(string token)
- {
- if (string.IsNullOrEmpty(token)) return false;
- try
- {
- var tokenHandler = new JwtSecurityTokenHandler();
- var key = Encoding.ASCII.GetBytes(_jwtSecret);
- // 定义 TokenValidationParameters 用于验证 JWT
- var validationParameters = new TokenValidationParameters
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = new SymmetricSecurityKey(key),
- ValidateIssuer = false,
- ValidateAudience = false,
- ClockSkew = TimeSpan.Zero
- };
- // 验证 JWT 并返回解析后的 Token
- SecurityToken validatedToken;
- var principal = tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
- // 从 ClaimsPrincipal 对象中提取用户名
- var claim = principal.FindFirst(ClaimTypes.Name);
- if (claim != null)
- {
- var getname = claim.Value; // 获取用户名
- return true; // 验证成功
- }
- return false; // 用户名未找到
- }
- catch
- {
- return false; // 验证失败
- }
- }
- }
复制代码 【Home/Index前端】(Main/Index不展示了= =)- @{
- ViewData["Title"] = "Home";
- }
- <h1>Login</h1>
- <form method="post" action="/Home">
- <div>
- <label for="username">Username:</label>
- <input type="text" id="username" name="username" required />
- </div>
- <div>
- <label for="password">Password:</label>
- <input type="password" id="password" name="password" required />
- </div>
- <button type="submit">Login</button>
- </form>
- @if (ViewBag.ErrorMessage != null)
- {
- <p style="color:red;">@ViewBag.ErrorMessage</p>
- }
复制代码 【appsettings.json】- {
- "ConnectionStrings": {
- "DefaultConnection": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"
- },
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "AllowedHosts": "*",
- "Jwt": {
- "Key": "123456",
- "Issuer": "MyWebApp"
- }
- }
复制代码 【Progarm.cs】- using Microsoft.AspNetCore.Authentication.JwtBearer;
- using Microsoft.IdentityModel.Tokens;
- using System.Text;
- var builder = WebApplication.CreateBuilder(args);
- // Add services to the container.
- builder.Services.AddControllersWithViews();
- //加一个session
- //builder.Services.AddSession(options =>
- //{
- // options.IdleTimeout = TimeSpan.FromMinutes(3); // 3分钟过期
- // options.Cookie.HttpOnly = true;
- // options.Cookie.IsEssential = true;
- //});
- // JWT 相关的配置开始
- var jwtSettings = builder.Configuration.GetSection("Jwt");
- var key = Encoding.ASCII.GetBytes(jwtSettings["Key"]);
- // 配置JWT认证服务
- builder.Services.AddAuthentication(x =>
- {
- x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
- })
- .AddJwtBearer(x =>
- {
- x.RequireHttpsMetadata = false;//设置为 false 表示不强制使用 HTTPS(在开发环境中可能是这样,但在生产环境中通常应设置为 true)。
- x.SaveToken = true;//SaveToken 为 true 表示在认证成功后,将 JWT 令牌保存到 HttpContext 中。
- x.TokenValidationParameters = new TokenValidationParameters
- {
- ValidateIssuerSigningKey = true,//true 表示验证 JWT 的签名密钥,以确保令牌未被篡改。
- IssuerSigningKey = new SymmetricSecurityKey(key),//指定了用于验证签名的密钥。key 是从配置文件中读取的密钥。
- ValidateIssuer = true,//true 表示验证 JWT 的发行者(Issuer),确保令牌来自预期的来源。
- ValidateAudience = true,//true 表示验证受众(Audience),确保令牌是为预期的接收者颁发的。
- ValidIssuer = jwtSettings["Issuer"],//指定了一个有效的发行者(Issuer)值
- ValidAudience = jwtSettings["Issuer"], // 指定了一个有效的受众(Audience)值,一般是同上的
- ClockSkew = TimeSpan.Zero//允许一些时间差异(例如,服务器和客户端时间不一致)的情况,但在此配置中被禁用了。
- };
- });// JWT 相关的配置结束
- var app = builder.Build();
- // Configure the HTTP request pipeline.
- if (!app.Environment.IsDevelopment())
- {
- app.UseExceptionHandler("/Home/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
- app.UseHttpsRedirection();
- app.UseStaticFiles();
- app.UseRouting();
- app.UseAuthentication(); // 确保认证在授权之前使用
- app.UseAuthorization();
- //使用session
- //app.UseSession();
- app.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
- app.Run();
复制代码
|