• IdentityServer4实现单点登录统一认证


    开发环境:

    vs2017 、net Core 2.1、sqlserver2012

    一。搭建IdentityServer4服务端

    打开VS2017,新建 netcore项目:    名字叫:IdentityS4, 然后选择webMVC这个,如下图:

    引进安装依赖项:IdentityServer4

    设置该项目的地址为:http://localhost:5000

    新建一个配置文件类:Config.cs  代码如下:

    复制代码

    public class Config
        {
            // scopes define the resources in your system
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new List<IdentityResource>
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Profile(),
                };
            }
    
            // clients want to access resources (aka scopes)
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>
                {
                    // OpenID Connect隐式流客户端(MVC)
                    new Client
                    {
                        ClientId = "mvc",
                        ClientName = "MVC Client",
                        AllowedGrantTypes = GrantTypes.Implicit,//隐式方式
                        RequireConsent=false,//如果不需要显示否同意授权 页面 这里就设置为false
                        RedirectUris = { "http://localhost:5002/signin-oidc" },//登录成功后返回的客户端地址
                        PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },//注销登录后返回的客户端地址
    
                        AllowedScopes =//下面这两个必须要加吧 不太明白啥意思
                        {
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile
                        }
                    }
                };
            }
        }

    复制代码

    在Startup.cs的ConfigureServices方法中注入Ids4服务,如下面红色部分代码:

    复制代码

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
                services.AddIdentityServer()//Ids4服务
                    .AddDeveloperSigningCredential()
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryClients(Config.GetClients());//把配置文件的Client配置资源放到内存
    
            }

    复制代码

    在Startup.cs的Configure方法中添加ids4服务中间件(注意要放在UseMvc之前就可以):

    app.UseIdentityServer();

    现在ids4本身的基本的配置弄好了,下面我们要开始弄跟数据库相关的东西了,大家想想,既然要登录,那肯定需要连接数据库并且读取出其中的用户信息去验证,比如账号、密码。好的,那我们就按照下面一步一步来做

    添加DbContext类 名字叫:EFContext.cs ,代码如下(其中红色部分是我们待会需要添加的实体类,也就是对应数据库里面的用户表Admin):

    复制代码

    public class EFContext : DbContext
        {
            public EFContext(DbContextOptions<EFContext> options) : base(options)
            {
    
            }
    
            #region 实体集
    
            public DbSet<Admin> Admin { get; set; }//注意 这里这个Admin不能写成Admins否则会报错找不到Admins 因为我们现在数据库和表是现成的 这里就相当于实体对应的数据库是Admin
    
            #endregion
        }

    复制代码

    添加一个Admin.cs的实体类,对应数据库里面的用户表Admin (然后把这个实体类添加到上一步的EFContext中,也就是上一步代码的红色部分)

    复制代码

    public class Admin
        {
            public int Id { get; set; }
            public DateTime CreateDate { get; set; }
            public string UserName { get; set; }
            public string Password { get; set; }
            public string Remark { get; set; }
        }

    复制代码

    在Startup.cs的ConfigureServices方法中注入 EFContext,如下面红色部分代码:

    复制代码

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<EFContext>(options=>options.UseSqlServer(Configuration.GetConnectionString("conn")));//注入DbContext
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
                services.AddIdentityServer()//Ids4服务
                    .AddDeveloperSigningCredential()
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryClients(Config.GetClients());//把配置文件的Client配置资源放到内存
    
            }

    复制代码

    接下来,我们就要写Admin这个实体类跟数据库打交道的代码了,比如增删改查啊,在net中一般交DAL层,在netCore中 一般交services层,要注意的是 netcore的框架是IOC的框架,依赖注入的,所以这个services层需要接口的形式!

    新建一个接口:IAdminService.cs 代码如下:

    public interface IAdminService
        {
            Task<Admin> GetByStr(string username, string pwd);//根据用户名和密码查找用户
        }

    新建实现该接口的类AdminService.cs

    复制代码

    public class AdminService:IAdminService
        {
            public EFContext db;
            public AdminService(EFContext _efContext)
            {
                db = _efContext;
            }
            /// <summary>
            /// 验证用户,成功则返回用户信息,否则返回null
            /// </summary>
            /// <param name="username"></param>
            /// <param name="pwd"></param>
            /// <returns></returns>
            public async Task<Admin> GetByStr(string username, string pwd)
            {
                Admin m=await db.Admin.Where(a => a.UserName == username && a.Password == pwd).SingleOrDefaultAsync();
                if (m!=null)
                {
                    return m;
                }
                else
                {
                    return null;
                }
            }
        }    

    复制代码

    在Startup.cs的ConfigureServices方法中注入 service层,如下面红色部分代码:

    复制代码

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<EFContext>(options=>options.UseSqlServer(Configuration.GetConnectionString("conn")));//注入DbContext
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
                services.AddIdentityServer()//Ids4服务
                    .AddDeveloperSigningCredential()
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryClients(Config.GetClients());//把配置文件的Client配置资源放到内存
    
                services.AddTransient<IAdminService,AdminService>();//service注入
            }

    复制代码

    在配置文件appsettings.json中添加数据库连接字符串如下红色部分代码:

    复制代码

    {
      "ConnectionStrings": { "conn": "server=.;database=blogcore;uid=sa;pwd=123" }, 
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*"
    }

    复制代码

    至此,应该是可以正确的连接数据库的,大家可以去Home控制器中查询点数据测试下显示到首页,保证能连接数据库成功的查询出数据就可以。

    接下来 我们来做登录页面

    新增一个控制器AccountController,代码如下:

    复制代码

    public class AccountController : Controller
        {
            private IAdminService _adminService;//自己写的操作数据库Admin表的service
            private readonly IIdentityServerInteractionService _interaction;
            private readonly IClientStore _clientStore;
            private readonly IAuthenticationSchemeProvider _schemeProvider;
            private readonly IEventService _events;
            public AccountController(IIdentityServerInteractionService interaction,
                IClientStore clientStore,
                IAuthenticationSchemeProvider schemeProvider,
                IEventService events,
                IAdminService adminService)
            {
                _interaction = interaction;
                _clientStore = clientStore;
                _schemeProvider = schemeProvider;
                _events = events;
                _adminService = adminService;
            }
    
            /// <summary>
            /// 登录页面
            /// </summary>
            [HttpGet]
            public async Task<IActionResult> Login(string returnUrl=null)
            {
                ViewData["returnUrl"] = returnUrl;
                return View();
            }
    
            /// <summary>
            /// 登录post回发处理
            /// </summary>
            [HttpPost]
            public async Task<IActionResult> Login(string userName, string password,string returnUrl=null)
            {
                ViewData["returnUrl"] = returnUrl;
                Admin user = await _adminService.GetByStr(userName, password);
                if (user!=null)
                {
                    AuthenticationProperties props= new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1))
                    };
                    await HttpContext.SignInAsync(user.Id.ToString(), user.UserName, props);
                    if (returnUrl!=null)
                    {
                        return Redirect(returnUrl);
                    }
    
                    return View();
                }
                else
                {
                    return View();
                }
            }
        }

    复制代码

    添加登录view视图,代码如下:

    复制代码

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Login</title>
    </head>
    <body>
    
        <div align="center">
            <h1>统一认证登录中心</h1>
            <form action="/Account/Login" method="post">
                用户名:<input type="text" name="userName" /><br />
                密 码:<input type="password" name="password" /><input type="hidden" name="returnUrl" value="@ViewData["returnUrl"]" /> <br />
                <input type="submit" value="登录" />
            </form>
        </div>
    </body>
    </html>

    复制代码

    至此,IdentityServer4服务端的工作完成,接下来我们要开始建客户端了,也就是需要保护的MVC网站

    二。搭建客户端

    新建一个名为 MvcClient 的 

    把地址设置为:http://localhost:5002

    在Startup.cs的ConfigureServices方法中添加如下红色部分代码(主要用来配置认证中心ids4的及自己作为客户端的认证信息):

    复制代码

    public void ConfigureServices(IServiceCollection services)
            {
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    
                services.AddAuthentication(options =>
                    {
                        options.DefaultScheme = "Cookies";
                        options.DefaultChallengeScheme = "oidc";
                    })
                    .AddCookie("Cookies")
                    .AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = "Cookies";
    
                        options.Authority = "http://localhost:5000";
                        options.RequireHttpsMetadata = false;
    
                        options.ClientId = "mvc";
                        options.SaveTokens = true;
                    });
    
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            }

    复制代码

    在 Configure方法中添加这行代码(需要在UseMvc之前就可以):

    app.UseAuthentication();

    到此,客户端跟统一认证的信息就配置完了。接下来我们把Home控制器上面加上需要验证的标志:[Authorize]

    我们把默认的Index视图页面html代码去掉,改成如下(主要用来显示下授权后拿到的用户信息):

    复制代码

    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div align="center"><h1>这里是受保护的客户端首页</h1></div>
    <h3>User claims</h3>
    
    <dl>
        @foreach (var claim in User.Claims)
        {
            <dt>@claim.Type</dt>
            <dd>@claim.Value</dd>
    
        }
    </dl>

    复制代码

    到此,客户端的工作也做完了,下面我们要开始启动项目了

    设置项目为多项目启动:解决方案上右键-属性

    现在我们启动项目:服务器项目和 客户端都运行了,但是客户端会直接跳转到服务端登录页面

    服务端

    客户端(5002)跳转过来的登录页面:

    然后输入正确账号密码 点击登录认证通过之后就跳转回 客户端网站去了

    至此 ,例子结束!

    从这个例子中,咱们可以再加几个客户端网站,然后统一到这个ids4认证,这样就达到了单点登录统一认证的效果了!

    源码下载:https://pan.baidu.com/s/1HRiAF7LMinCh03AZNArfcQ

  • 相关阅读:
    C语言C++编程学习:排序原理分析
    Ubuntu下开机进程管理工具sysvrcconf
    康托展开
    USACO 3.2 Magic Squares题解
    『转』ubuntu的电池管理
    poj1061青蛙的约会解题报告
    Dancing Links
    【转】史上最强vim配置文件vimrc
    四柱汉诺塔
    又遇欧拉 转载之
  • 原文地址:https://www.cnblogs.com/lhxsoft/p/12551938.html
Copyright © 2020-2023  润新知