上一篇文章说到JWT API 跨域验证实战,这一篇从完整login 打,跨域访问带有权限的页面。
资源
SiteA
SiteB
Summery
jS:
SiteA js postMessageToken to siteB,siteB get the Token, and send request by adding header and the Token, then redirect the page need to verify
Model
UserInfo // 保存用户信息,和验证内容
- public class UserInfo
- {
- ///
- /// name
- ///
- public string Name { get; set; }
-
- ///
- /// Email
- ///
- public string Email { get; set; }
- ///
- /// PassWord
- ///
- public string PassWord { get; set; }
- ///
- /// role
- ///
- public List<string> Roles { get; set; }
-
- ///
- /// is admin
- ///
- public bool IsAdmin { get; set; }
-
- ///
- /// expiry date
- ///
- public DateTime? ExpiryDateTime { get; set; }
- }
JwtResult
JWT加密,解密过程
Token的创建
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using JWT;
- using JWT.Algorithms;
- using JWT.Serializers;
- using Newtonsoft.Json;
-
- namespace MVCWeb.Models
- {
- public class JwtResult {
- public string JwtCode { get; set; }
- public string StatusCode { get; set; }
- public string Message { get; set; }
- }
- public class JwtHelper
- {
- private string m_Secret = "THC";
- public string EncodeJwt(UserInfo userInfo)
- {
- IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
- IJsonSerializer serializer = new JsonNetSerializer();
- IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
- IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
- return encoder.Encode(userInfo, m_Secret);
- }
-
- public UserInfo DecodeJwt(string token)
- {
- IJsonSerializer serializer = new JsonNetSerializer();
- IDateTimeProvider provider = new UtcDateTimeProvider();
- IJwtValidator validator = new JwtValidator(serializer, provider);
- IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
- var algorithm = new HMACSHA256Algorithm();
- IJwtDecoder decoder = new JwtDecoder(serializer, validator,urlEncoder, algorithm);
- var userInfo = decoder.DecodeToObject
(token, m_Secret, verify: true);//token为之前生成的字符串 - return userInfo;
- }
- public JwtResult CreateToken(string UserName, string PassWord)
- {
- if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(PassWord))
- throw new Exception("参数为空");
-
- JwtResult jwtResult;
- try
- {
- //var param = HttpContext.Request["UserName"];
- //param = HttpContext.Request["PassWord"];
- if (!UserName.Equals("test") || !PassWord.Equals("test"))
- {
- throw new Exception("用户密码不正确。");
- }
-
- UserInfo pUserLoginInfo = new UserInfo() { Name = UserName, PassWord = PassWord };
- JwtHelper pHelper = new JwtHelper();
- string sJwt = pHelper.EncodeJwt(pUserLoginInfo);
- jwtResult = new JwtResult()
- {
- JwtCode = sJwt,
- StatusCode = "200",
- Message = "success"
- };
- return jwtResult;
- }
- catch (Exception ex)
- {
- jwtResult = new JwtResult()
- {
- JwtCode = "",
- StatusCode = "403",
- Message = ex.Message
- };
- }
-
- return jwtResult;
- }
- }
- }
AppAuthorizeAttribute,自动验证过程,本代码支持两证验证,一是登录验证,二是头部auto验证,任何一种满足都可以拥有访问权限,需要注意点,无论哪种验证,等待验证额通过后,我都会把Token对象保存在Session中,//System.Web.HttpContext.Current.Session["tokenInfo"] = jr,目的是访问有权限的页面时候,便于通过验证
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using MVCWeb.Models;
-
- namespace MVCWeb.Filters
- {
- public class AppAuthorizeAttribute : AuthorizeAttribute
- {
- ///
- /// 验证入口
- ///
- ///
- public override void OnAuthorization(AuthorizationContext filterContext)
- {
- base.OnAuthorization(filterContext);
- }
-
-
- protected override bool AuthorizeCore(HttpContextBase httpContext)
- {
- JwtHelper pHelper = new JwtHelper();
- try
- {
- JwtResult jr = (JwtResult)GHelper.GetCurrentTokenInfo();
- //前端请求api时会将token存放在名为"auth"的请求头中
- var authHeader = httpContext.Request.Headers["auth"];
- /*
- if (authHeader == null)
- {
- httpContext.Response.StatusCode = 403;
- return false;
- }
- */
-
- if (authHeader != null)
- {
- jr = new JwtResult();
- jr.JwtCode = authHeader;
- }
- else if (jr != null)
- {
- }
- else {
- httpContext.Response.StatusCode = 403;
- return false;
- }
-
-
- var userinfo = pHelper.DecodeJwt(jr.JwtCode);
- if (userinfo != null)
- {
-
- jr.Message = "success";
- jr.StatusCode = "200";
- System.Web.HttpContext.Current.Session["tokenInfo"] = jr;
- return true;
- }
-
- httpContext.Response.StatusCode = 403;
- return false;
- }
- catch
- {
- httpContext.Response.StatusCode = 403;
- return false;
- }
- }
-
- ///
- /// 验证失败处理
- ///
- ///
- protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
- {
- System.Web.HttpContext.Current.Session.Clear();
- base.HandleUnauthorizedRequest(filterContext);
- if (filterContext.HttpContext.Response.StatusCode == 403)
- {
- //filterContext.Result = new RedirectResult("/Error");
- filterContext.HttpContext.Response.Redirect("/account/login");
- }
- }
- }
- }
AccountController
登录后保存token到sesssion
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using MVCWeb.Models;
-
- namespace MVCWeb.Controllers
- {
- public class AccountController : Controller
- {
- // GET: Account
- public ActionResult Index()
- {
- return View();
- }
-
- [HttpGet] //返回页面,展示登录页面
- public ActionResult Login()
- {
- return View();
- }
-
-
- [HttpPost] //提交登录,开始登录时执行业务逻辑
- public ActionResult Login(UserInfo user)
- {
- /*
- if (ModelState.IsValid) //触发实体验证,如果返回true,则通过验证登录成功
- {
- if (user.Name == "test" && user.PassWord == "test")
- {
- return base.Redirect("/Home/Index");
- }
- else {
- return Content("用户名或密码有误!");
- }
- }
- return base.Redirect("Home/Index");
- */
- if (ModelState.IsValid)
- {
- JwtHelper jh = new JwtHelper();
- JwtResult jr = jh.CreateToken(user.Name, user.PassWord);
- System.Web.HttpContext.Current.Session["tokenInfo"] = jr;
- if (jr.Message == "success")
- {
- //return RedirectToAction("index", "Home", jr); //url后有参数
- return base.Redirect("/Home/Index");
- }
- else
- {
- return Content("用户名或密码有误!");
- }
- }
- return Content("fail to login!");
- }
- }
- }
HomeController
将被访问带有权限的页面 [AppAuthorize],首先需要通过验证,才能访问
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using MVCWeb.Filters;
- using MVCWeb.Models;
-
- namespace MVCWeb.Controllers
- {
- [AppAuthorize]
- public class HomeController : Controller
- {
- // GET: Home
- public ActionResult Index()
- {
- //to do....
- JwtResult jr = (JwtResult)GHelper.GetCurrentTokenInfo();
- //解析token => jr
- //...
-
- UserInfo pUser = new UserInfo()
- {
- Name = "Test",
- PassWord = "Test"
- };
- //ViewBag.Token = jr.JwtCode;
- //ViewBag.Message = jr.Message;
- //ViewBag.Status = jr.StatusCode;
-
- return View(pUser);
- }
- public string test() {
- return "test";
- }
- }
- }
THCController
未经过授权的页面,目的是仅供跨域者使用,是一个空页面,或者中转页面
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using MVCWeb.Filters;
- using MVCWeb.Models;
-
- namespace MVCWeb.Controllers
- {
- //[AppAuthorize]
- public class THCController : Controller
- {
- // GET: THC
- public ActionResult Index()
- {
- return View();
- }
- }
- }