• JWT API 跨域验证实战 仅供参考


    上一篇文章说到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

    Server:

            MVC框架

            Model

                    UserInfo // 保存用户信息,和验证内容

    1. public class UserInfo
    2. {
    3. ///
    4. /// name
    5. ///
    6. public string Name { get; set; }
    7. ///
    8. /// Email
    9. ///
    10. public string Email { get; set; }
    11. ///
    12. /// PassWord
    13. ///
    14. public string PassWord { get; set; }
    15. ///
    16. /// role
    17. ///
    18. public List<string> Roles { get; set; }
    19. ///
    20. /// is admin
    21. ///
    22. public bool IsAdmin { get; set; }
    23. ///
    24. /// expiry date
    25. ///
    26. public DateTime? ExpiryDateTime { get; set; }
    27. }

                    JwtResult

                    JWT加密,解密过程

                    Token的创建

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using JWT;
    7. using JWT.Algorithms;
    8. using JWT.Serializers;
    9. using Newtonsoft.Json;
    10. namespace MVCWeb.Models
    11. {
    12. public class JwtResult {
    13. public string JwtCode { get; set; }
    14. public string StatusCode { get; set; }
    15. public string Message { get; set; }
    16. }
    17. public class JwtHelper
    18. {
    19. private string m_Secret = "THC";
    20. public string EncodeJwt(UserInfo userInfo)
    21. {
    22. IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
    23. IJsonSerializer serializer = new JsonNetSerializer();
    24. IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    25. IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
    26. return encoder.Encode(userInfo, m_Secret);
    27. }
    28. public UserInfo DecodeJwt(string token)
    29. {
    30. IJsonSerializer serializer = new JsonNetSerializer();
    31. IDateTimeProvider provider = new UtcDateTimeProvider();
    32. IJwtValidator validator = new JwtValidator(serializer, provider);
    33. IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    34. var algorithm = new HMACSHA256Algorithm();
    35. IJwtDecoder decoder = new JwtDecoder(serializer, validator,urlEncoder, algorithm);
    36. var userInfo = decoder.DecodeToObject(token, m_Secret, verify: true);//token为之前生成的字符串
    37. return userInfo;
    38. }
    39. public JwtResult CreateToken(string UserName, string PassWord)
    40. {
    41. if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(PassWord))
    42. throw new Exception("参数为空");
    43. JwtResult jwtResult;
    44. try
    45. {
    46. //var param = HttpContext.Request["UserName"];
    47. //param = HttpContext.Request["PassWord"];
    48. if (!UserName.Equals("test") || !PassWord.Equals("test"))
    49. {
    50. throw new Exception("用户密码不正确。");
    51. }
    52. UserInfo pUserLoginInfo = new UserInfo() { Name = UserName, PassWord = PassWord };
    53. JwtHelper pHelper = new JwtHelper();
    54. string sJwt = pHelper.EncodeJwt(pUserLoginInfo);
    55. jwtResult = new JwtResult()
    56. {
    57. JwtCode = sJwt,
    58. StatusCode = "200",
    59. Message = "success"
    60. };
    61. return jwtResult;
    62. }
    63. catch (Exception ex)
    64. {
    65. jwtResult = new JwtResult()
    66. {
    67. JwtCode = "",
    68. StatusCode = "403",
    69. Message = ex.Message
    70. };
    71. }
    72. return jwtResult;
    73. }
    74. }
    75. }

    Filter:      

      AppAuthorizeAttribute,自动验证过程,本代码支持两证验证,一是登录验证,二是头部auto验证,任何一种满足都可以拥有访问权限,需要注意点,无论哪种验证,等待验证额通过后,我都会把Token对象保存在Session中,//System.Web.HttpContext.Current.Session["tokenInfo"] = jr,目的是访问有权限的页面时候,便于通过验证

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using MVCWeb.Models;
    7. namespace MVCWeb.Filters
    8. {
    9. public class AppAuthorizeAttribute : AuthorizeAttribute
    10. {
    11. ///
    12. /// 验证入口
    13. ///
    14. ///
    15. public override void OnAuthorization(AuthorizationContext filterContext)
    16. {
    17. base.OnAuthorization(filterContext);
    18. }
    19. protected override bool AuthorizeCore(HttpContextBase httpContext)
    20. {
    21. JwtHelper pHelper = new JwtHelper();
    22. try
    23. {
    24. JwtResult jr = (JwtResult)GHelper.GetCurrentTokenInfo();
    25. //前端请求api时会将token存放在名为"auth"的请求头中
    26. var authHeader = httpContext.Request.Headers["auth"];
    27. /*
    28. if (authHeader == null)
    29. {
    30. httpContext.Response.StatusCode = 403;
    31. return false;
    32. }
    33. */
    34. if (authHeader != null)
    35. {
    36. jr = new JwtResult();
    37. jr.JwtCode = authHeader;
    38. }
    39. else if (jr != null)
    40. {
    41. }
    42. else {
    43. httpContext.Response.StatusCode = 403;
    44. return false;
    45. }
    46. var userinfo = pHelper.DecodeJwt(jr.JwtCode);
    47. if (userinfo != null)
    48. {
    49. jr.Message = "success";
    50. jr.StatusCode = "200";
    51. System.Web.HttpContext.Current.Session["tokenInfo"] = jr;
    52. return true;
    53. }
    54. httpContext.Response.StatusCode = 403;
    55. return false;
    56. }
    57. catch
    58. {
    59. httpContext.Response.StatusCode = 403;
    60. return false;
    61. }
    62. }
    63. ///
    64. /// 验证失败处理
    65. ///
    66. ///
    67. protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    68. {
    69. System.Web.HttpContext.Current.Session.Clear();
    70. base.HandleUnauthorizedRequest(filterContext);
    71. if (filterContext.HttpContext.Response.StatusCode == 403)
    72. {
    73. //filterContext.Result = new RedirectResult("/Error");
    74. filterContext.HttpContext.Response.Redirect("/account/login");
    75. }
    76. }
    77. }
    78. }

            Controls:

    AccountController

    登录后保存token到sesssion

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using MVCWeb.Models;
    7. namespace MVCWeb.Controllers
    8. {
    9. public class AccountController : Controller
    10. {
    11. // GET: Account
    12. public ActionResult Index()
    13. {
    14. return View();
    15. }
    16. [HttpGet] //返回页面,展示登录页面
    17. public ActionResult Login()
    18. {
    19. return View();
    20. }
    21. [HttpPost] //提交登录,开始登录时执行业务逻辑
    22. public ActionResult Login(UserInfo user)
    23. {
    24. /*
    25. if (ModelState.IsValid) //触发实体验证,如果返回true,则通过验证登录成功
    26. {
    27. if (user.Name == "test" && user.PassWord == "test")
    28. {
    29. return base.Redirect("/Home/Index");
    30. }
    31. else {
    32. return Content("用户名或密码有误!");
    33. }
    34. }
    35. return base.Redirect("Home/Index");
    36. */
    37. if (ModelState.IsValid)
    38. {
    39. JwtHelper jh = new JwtHelper();
    40. JwtResult jr = jh.CreateToken(user.Name, user.PassWord);
    41. System.Web.HttpContext.Current.Session["tokenInfo"] = jr;
    42. if (jr.Message == "success")
    43. {
    44. //return RedirectToAction("index", "Home", jr); //url后有参数
    45. return base.Redirect("/Home/Index");
    46. }
    47. else
    48. {
    49. return Content("用户名或密码有误!");
    50. }
    51. }
    52. return Content("fail to login!");
    53. }
    54. }
    55. }

    HomeController

    将被访问带有权限的页面  [AppAuthorize],首先需要通过验证,才能访问

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using MVCWeb.Filters;
    7. using MVCWeb.Models;
    8. namespace MVCWeb.Controllers
    9. {
    10. [AppAuthorize]
    11. public class HomeController : Controller
    12. {
    13. // GET: Home
    14. public ActionResult Index()
    15. {
    16. //to do....
    17. JwtResult jr = (JwtResult)GHelper.GetCurrentTokenInfo();
    18. //解析token => jr
    19. //...
    20. UserInfo pUser = new UserInfo()
    21. {
    22. Name = "Test",
    23. PassWord = "Test"
    24. };
    25. //ViewBag.Token = jr.JwtCode;
    26. //ViewBag.Message = jr.Message;
    27. //ViewBag.Status = jr.StatusCode;
    28. return View(pUser);
    29. }
    30. public string test() {
    31. return "test";
    32. }
    33. }
    34. }

           THCController

    未经过授权的页面,目的是仅供跨域者使用,是一个空页面,或者中转页面

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using MVCWeb.Filters;
    7. using MVCWeb.Models;
    8. namespace MVCWeb.Controllers
    9. {
    10. //[AppAuthorize]
    11. public class THCController : Controller
    12. {
    13. // GET: THC
    14. public ActionResult Index()
    15. {
    16. return View();
    17. }
    18. }
    19. }

  • 相关阅读:
    RocketMQ源码(十八)之消费者PullMessageService
    Java开发规范
    html网页设计大学生作业成品——公益校园网站设计与实现(HTML+CSS+JavaScript)
    Docker 日志管理 - ELK
    【JavaScript】JS语法入门到实战
    Jenkins详细安装配置部署--超详细
    Vivado 2018.3 安装步骤及 license 获取
    Spring 如何使用JDK动态代理呢?
    华为云安装Docker,在其中安装Tomcat运行Html项目一步到位
    Power BI 和 Tableau的区别
  • 原文地址:https://blog.csdn.net/cmmsgwcpd/article/details/126589882