NET Core【IdentityServer4单点登录】+【退出登录】

第一天接触NetCore,感觉坑很多,其他都还良好

 

 

    比如说我们现在有三个系统,一个是商品系统,一个是订单系统,另外一个就是单独的登录系统,

    当我们要访问商品系统或者订单系统的时候,我们首先得判断一下我们的本地客户端是否有登录缓存,

    如果没有的话就会再到统一的认证中心去找,如果还是没有,就会自动跳转到登录页面,登录成功后,

    我们要访问订单系统或者商品系统时,就直接在自己本地客户端取出登录缓存即可,

    但是得做一下相关的操作,在订单和商品服务的StartUp.cs里面都要添加一下服务记录登录状态

 

  1.    
  2.    services.AddAuthentication(options =>  
  3.    {
  4.           options.DefaultScheme = "Cookies";
  5.           options.DefaultChallengeScheme = "oidc";
  6.       })
  7.           .AddCookie("Cookies")
  8.            .AddOpenIdConnect("oidc", options =>
  9.             {
  10.                   options.SignInScheme = "Cookies";
  11.                   options.Authority = "http://localhost:56772"; //登陆中心的地址
  12.                   options.RequireHttpsMetadata = false;
  13.                   options.ClientId = ".net58_Order";
  14.                   options.SaveTokens = true;
  15.              });

   

 以及添加身份验证和session中间件

  1.  //身份验证
  2.  app.UseAuthentication();
  3.   //启用session中间件
  4.   app.UseSession();

这几样都是必不可少的,另外我们还得在登录系统里面加一个Config.cs类

  1. public class Config
  2.     {
  3.         // scopes define the resources in your system
  4.         public static IEnumerable<IdentityResource> GetIdentityResources()
  5.         {
  6.             return new List<IdentityResource>
  7.             {
  8.                 new IdentityResources.OpenId(),
  9.                 new IdentityResources.Profile(),
  10.             };
  11.         }
  12.         // clients want to access resources (aka scopes)
  13.         public static IEnumerable<Client> GetClients()
  14.         {
  15.             return new List<Client>
  16.             {
  17.                 // OpenID Connect隐式流客户端(MVC)
  18.                 new Client
  19.                 {
  20.                     ClientId = ".net58_Order", //订单系统
  21.                     ClientName = "MVC Client",
  22.                     AllowedGrantTypes = GrantTypes.Implicit,//隐式方式
  23.                     RequireConsent=false,//如果不需要显示否同意授权 页面 这里就设置为false                      
  24.                     RedirectUris = { "http://localhost:56574/signin-oidc" },//登录成功后返回的订单系统客户端地址
  25.                     //PostLogoutRedirectUris = { "http://localhost:56574/signout-callback-oidc" },//注销登录后返回的客户端地址
  26.                     AllowedScopes =
  27.                     {
  28.                         IdentityServerConstants.StandardScopes.OpenId,
  29.                         IdentityServerConstants.StandardScopes.Profile
  30.                     }
  31.                 },
  32.                  new Client
  33.                 {
  34.                     ClientId = ".net58_product", //商品系统
  35.                     ClientName = "MVC Client",
  36.                     AllowedGrantTypes = GrantTypes.Implicit,//隐式方式
  37.                     RequireConsent=false,//如果不需要显示否同意授权 页面 这里就设置为false                      
  38.                     RedirectUris = { "http://localhost:55447/signin-oidc" },//登录成功后返回的商品系统客户端地址
  39.                     //PostLogoutRedirectUris = { "http://localhost:55447/signout-callback-oidc" },//注销登录后返回的客户端地址
  40.                     AllowedScopes =
  41.                     {
  42.                         IdentityServerConstants.StandardScopes.OpenId,
  43.                         IdentityServerConstants.StandardScopes.Profile
  44.                     }
  45.                 }
  46.             };
  47.         }
  48.     }

 

一定要记得在订单和商品将属性[Authorize]置于整个Controller之上。当用户有操作时,进入控制器前都会先验证用户是否登录,或者存储用户信息过期从而返回登录界面。

 

  1.    [Authorize]

  

//查询用户名和密码

  1. public class UserDAL : IUserDAL
  2.     {
  3.         private readonly MyContext myContext;
  4.         
  5.         //构造函数注入
  6.         public UserDAL(MyContext myContext2)
  7.         {
  8.             myContext = myContext2;
  9.         }
  10.         public Users Login(string UserName, string Userpwd)
  11.         {
  12.             Users users = myContext.Users.Where(a => a.UserName == UserName && a.UserPwd == Userpwd).FirstOrDefault();
  13.             return users;
  14.         }
  15.         //异步
  16.         public Task<Users> LoginAsync(string UserName, string Userpwd)
  17.         {
  18.             Task.Run(() =>
  19.                 { 
  20.                 Users users = myContext.Users.Where(a => a.UserName == UserName && a.UserPwd == Userpwd).FirstOrDefault();
  21.                 return users;
  22.              });
  23.             return null;
  24.         }
  25.     }

 

IUserDAL接口

  1. namespace LoginSystem.DAL.Interface
  2. {
  3.     public interface IUserDAL
  4.     {
  5.         Users Login(string UserName, string Userpwd);
  6.         Task<Users> LoginAsync(string UserName, string Userpwd);
  7.     }
  8. }

 

在登录系统的StartUp.cs类里面的这个ConfigureServices方法里面添加点配置

 

  1.    //配置依赖注入关系
  2.     services.AddTransient<IUserDAL, UserDAL>();
  3.       services.AddDbContext<MyContext>(option => {
  4.       
  5.        option.UseSqlServer("Data Source =.; Initial Catalog =My; User ID = sa; Password = 123456");
  6.        
  7.      });
  8.              
  9.   services.AddIdentityServer()//Ids4服务
  10.   .AddDeveloperSigningCredential()//添加开发人员签名凭据
  11.   .AddInMemoryIdentityResources(Config.GetIdentityResources()) //添加内存apiresource
  12.   .AddInMemoryClients(Config.GetClients());//把配置文件的Client配置资源放到内存

 

另外在登录系统里面启用一下id这个服务,这个服务也需要我们自己下载,版本根据个人需求下就可以啦

  1. 下载包:install-package identityServer4 -version 2.1.1
  1.   //启用id4
  2.   app.UseIdentityServer();

 

再来说一下关于登录系统里面的登录,

NetCore里面是没有Session,我们要使用的话,得自己下载一下,需要哪种版本根据自己需求下

  1. 下载包:Install-package Microsoft.AspNetCore.Session -Version 2.1.1
  1.  public class AccountController : Controller
  2.     {
  3.         /// <summary>
  4.         /// 登录页面
  5.         /// </summary>
  6.         [HttpGet]
  7.         public IActionResult Login(string returnUrl = null)
  8.         {
  9.             ViewData["returnUrl"] = returnUrl;
  10.             return View();
  11.         }
  12.         
  13.         
  14.         //依赖注入
  15.         private readonly IIdentityServerInteractionService _interaction;
  16.         private readonly IUserDAL _userDAL;
  17.         public AccountController(IIdentityServerInteractionService interaction, IUserDAL userDAL )
  18.         {
  19.             _interaction = interaction;
  20.             _userDAL = userDAL;
  21.         }
  22.         
  23.         //内部跳转
  24.         private IActionResult RedirectToLocal(string returnUrl)
  25.         {
  26.             if (Url.IsLocalUrl(returnUrl))
  27.             {
  28.                 //如果是本地
  29.                 return Redirect(returnUrl);
  30.             }
  31.             return RedirectToAction(nameof(HomeController.Index), "Home");
  32.         }
  33.         /// <summary>
  34.         /// 登录post回发处理
  35.         /// </summary>
  36.         [HttpPost]
  37.         public async Task<IActionResult> Login(string userName, string password, string returnUrl = null)
  38.         {
  39.             ViewData["returnUrl"] = returnUrl;
  40.             
  41.             Users users =  _userDAL.Login(userName, password);
  42.             
  43.             //判断是否为空
  44.             if (users != null)
  45.             {
  46.                 AuthenticationProperties props = new AuthenticationProperties
  47.                 {
  48.                     IsPersistent = true,
  49.                     ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1)),
  50.                 };
  51.                 //注意这里应该引用Microsoft.AspNetCore.Http这个下面的
  52.                 await HttpContext.SignInAsync("2123", userName, props);
  53.                 //HttpContext.SignOutAsync();
  54.                 if (returnUrl != null)
  55.                 {
  56.                     return RedirectToLocal(returnUrl);//登陆成功跳转原地址
  57.                     //return Redirect("http://localhost:44396/home/index");
  58.                 }
  59.                 return View();
  60.             }
  61.             else
  62.             {
  63.                 return Content("登录失败");
  64.             }
  65.          }
  66.         }

 

登录页面的代码

  1. @{
  2.     Layout = null;
  3. }
  4. <!DOCTYPE html>
  5. <html>
  6. <head>
  7.     <meta name="viewport" content="width=device-width" />
  8.     <title>Login</title>
  9.     <script>
  10.         new Oidc.UserManager().signinRedirectCallback().then(function (user) {
  11.             alert("登录成功后跳转");
  12.             alert(user.state);
  13.             window.location = user.state;
  14.         }).catch(function (e) {
  15.             console.error(e);
  16.         });
  17.     </script>
  18. </head>
  19. <body>
  20.     <div align="center">
  21.         <h1>登录认证中心</h1>
  22.         <form method="post" action="/Account/Login">
  23.             用户名:<input type="text" name="userName" /><br />
  24.             密  码:<input type="password" name="password" />
  25.             <input type="hidden" name="returnUrl" value="@ViewData["returnUrl"]" /> <br />
  26.             <input type="submit" value="登录" />
  27.         </form>
  28.     </div>
  29. </body>
  30. </html>

如果没有登录,订单系统和商品系统都会自动跳转回到登录界面

 

 

登录成功后的订单页面和商品页面

 

再来说一下退出登录

 

首先在商品系统的index.cshtml页面,写一个退出登录的a标签事件

  1. <a href="/account/Logout" style="float:right;color:#ff0000;font-size:30px">退出登录</a>

 

接下来就是在登录系统里边写相关操作

  1.  //退出登录
  2.         private readonly IIdentityServerInteractionService _interaction;
  3.         public AccountController(IIdentityServerInteractionService interaction)
  4.         {
  5.             _interaction = interaction;
  6.         }
  7.         [HttpGet]
  8.         public async Task<IActionResult> Logout(string logoutId)
  9.         {
  10.             #region IdentityServer4 退出登录后,默认会跳转到Config.Client配置的PostLogoutRedirectUris地址,
  11.             //做如下改动,则会动态的跳转到原来的地址
  12.             var logout = await _interaction.GetLogoutContextAsync(logoutId);
  13.             await HttpContext.SignOutAsync();
  14.             if (logout.PostLogoutRedirectUri != null)
  15.             {
  16.                 return Redirect(logout.PostLogoutRedirectUri);
  17.             }
  18.             var refererUrl = Request.Headers["Referer"].ToString();
  19.             return Redirect(refererUrl);
  20.             #endregion
  21.         }

 

再到Home控制器里边向IdentityServer进行往返,目的清除单点登录会话

  1. public IActionResult Logout()
  2.  {
  3.     return SignOut("Cookies", "oidc");
  4.   }

步骤有点多,会被绕晕,得慢慢来,特别是那些地址,千万不能填错,坑也很多,得踩过之后才知道!

posted @ 2021-03-26 13:36  dreamw  阅读(717)  评论(0编辑  收藏  举报