Authenticating Website Members as Users in CKFinder v3

余生长醉 提交于 2019-12-05 12:17:37

First you'll need a connector between the ASP's Session and CKFinder's .Net authenticator. Here's an example that serializes ASP Session contents into JSON.

Put the connector.asp into a publicly accessible location. http://myaspwebsite.com/connector.asp for example.

connector.asp

<%@Language=VBScript CodePage=65001%>
<% Option Explicit %>
<!--#include file="JSON.asp"-->
<%
' obtain JSON.asp from https://github.com/tugrul/aspjson/archive/master.zip

' just for testing, must be removed in the production environment
Session("isEditor") = True
Session("isMember") = True

' only local requests allowed
' instead of local and remote ip comparison, a secret key can be used
If Request.ServerVariables("LOCAL_ADDR") <> Request.ServerVariables("REMOTE_ADDR") Then
    Response.Status = "403 Forbidden"
    Response.End
End If

Response.ContentType = "application/json"
Response.Charset = "utf-8"

Dim JSONObject, Key
Set JSONObject = jsObject()

For Each Key In Session.Contents
    If Not IsObject(Session.Contents(Key)) Then 'skip the objects cannot be serialized
        JSONObject(Key) = Session.Contents(Key)
    End If
Next

JSONObject.Flush
%>

CKFinder 3.3.0 comes with a default connector which can be found in /ckfinder/bin/CKSource.CKFinder.Connector.WebApp.dll, remove it.

Examine the following program and remember to replace builder.Map("/connector", SetupConnector); and new Uri("http://myaspwebsite.com/connector.asp"); with your own values.

It simply authenticates the users by checking ASP Session varaibles isEditor and isMember via connector.asp and finally claims the roles editor , member or none.

I assume that you have configured the roles editor and member in the web.config.

Then put the Shaggy.cs into /ckfinder/App_Code. Create App_Code directory if not exist. .Net files in this folder will be compiled on the fly.

For more information have a look at Shared Code Folders in ASP.NET Web Projects

Shaggy.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Newtonsoft.Json.Linq;
using Owin;

[assembly: Microsoft.Owin.OwinStartup(typeof(CKSource.CKFinder.Connector.Shaggy.Startup))]
namespace CKSource.CKFinder.Connector.Shaggy
{
    using FileSystem.Local;
    using FileSystem.Dropbox;
    using Core;
    using Core.Authentication;
    using Config;
    using Core.Builders;
    using Core.Logs;
    using Host.Owin;
    using Logs.NLog;
    using KeyValue.EntityFramework;

    public class Startup
    {
        public void Configuration(IAppBuilder builder)
        {
            LoggerManager.LoggerAdapterFactory = new NLogLoggerAdapterFactory();

            RegisterFileSystems();

            builder.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "ApplicationCookie",
                AuthenticationMode = AuthenticationMode.Active
            });

            //replace connector path with yours
            builder.Map("/connector", SetupConnector);
        }

        private static void RegisterFileSystems()
        {
            FileSystemFactory.RegisterFileSystem<LocalStorage>();
            FileSystemFactory.RegisterFileSystem<DropboxStorage>();
        }

        private static void SetupConnector(IAppBuilder builder)
        {
            var keyValueStoreProvider = new EntityFrameworkKeyValueStoreProvider("CacheConnectionString");
            var authenticator = new ShaggysAuthenticator();

            var connectorFactory = new OwinConnectorFactory();
            var connectorBuilder = new ConnectorBuilder();
            var connector = connectorBuilder
                .LoadConfig()
                .SetAuthenticator(authenticator)
                .SetRequestConfiguration(
                    (request, config) =>
                    {
                        config.LoadConfig();
                        config.SetKeyValueStoreProvider(keyValueStoreProvider);
                    })
                .Build(connectorFactory);

            builder.UseConnector(connector);
        }
    }

    public class ShaggysAuthenticator : IAuthenticator
    {
        // this method makes an http request on the background to gather ASP's all session contents and returns a JSON object
        // if the request contains ASP's session cookie(s)
        private static JObject GetAspSessionState(ICommandRequest requestContext)
        {
            // building Cookie header with ASP's session cookies
            var aspSessionCookies = string.Join(";",
                requestContext.Cookies.Where(cookie => cookie.Key.StartsWith("ASPSESSIONID"))
                    .Select(cookie => string.Join("=", cookie.Key, cookie.Value)));

            if (aspSessionCookies.Length == 0)
            {
                // logs can be found in /ckfinder/App_Data/logs
                LoggerManager.GetLoggerForCurrentClass().Info("No ASP session cookie found");
                // don't make an extra request to the connector.asp, there's no session initiated
                return new JObject();
            }

            //replace this URL with your connector.asp's
            var publicAspSessionConnectorUrl = new Uri("http://myaspwebsite.com/connector.asp");
            var localSafeAspSessionConnectorUrl = new UriBuilder(publicAspSessionConnectorUrl) { Host = requestContext.LocalIpAddress };

            using (var wCli = new WebClient())
                try
                {
                    wCli.Headers.Add(HttpRequestHeader.Cookie, aspSessionCookies);
                    wCli.Headers.Add(HttpRequestHeader.Host, publicAspSessionConnectorUrl.Host);
                    return JObject.Parse(wCli.DownloadString(localSafeAspSessionConnectorUrl.Uri));
                }
                catch (Exception ex) // returning an empty JObject object in any fault
                {
                    // logs can be found in /ckfinder/App_Data/logs
                    LoggerManager.GetLoggerForCurrentClass().Error(ex);
                    return new JObject();
                }
        }

        public Task<IUser> AuthenticateAsync(ICommandRequest commandRequest, CancellationToken cancellationToken)
        {
            var aspSessionState = GetAspSessionState(commandRequest);

            var roles = new List<string>();
            var isEditor = aspSessionState.GetNullSafeValue("isEditor", false);
            var isMember = aspSessionState.GetNullSafeValue("isMember", false);

            if (isEditor) roles.Add("editor");
            if (isMember) roles.Add("member");

            var isAuthenticated = isEditor || isMember;
            var user = new User(isAuthenticated, roles);
            return Task.FromResult((IUser)user);
        }
    }

    public static class JObjectExtensions
    {
        // an extension method to help case insensitive lookups with a default value to get avoid NullReferenceException
        public static T GetNullSafeValue<T>(this JObject jobj, string key, T defaultValue = default(T))
        {
            dynamic val = jobj.GetValue(key, StringComparison.OrdinalIgnoreCase);
            if (val == null) return defaultValue;
            return (T)val;
        }
    }
}

Now you should have a working CKFinder connector. Change the logic in the method AuthenticateAsync if you need and see how CKFinder handles your Classic ASP membership management.

Lesmian

Did you setup your custom authentication provider with ConnectorBuilder?

public ConnectorBuilder ConfigureConnector()
{
   var connectorBuilder = new ConnectorBuilder();
   connectorBuilder.SetAuthenticator(new MyAuthenticator());

   return connectorBuilder;
}

You can find full example here: http://docs.cksource.com/ckfinder3-net/configuration_by_code.html.

UPDATE

Additionally you should register ConnectorBuilder inside Startup class to add it to request pipeline:

public void Configuration(IAppBuilder appBuilder)
{
   var connectorBuilder = ConfigureConnector();
   var connector = connectorBuilder.Build(new OwinConnectorFactory());
   appBuilder.Map("/CKFinder/connector", builder => builder.UseConnector(connector));
}

All this is from a documentation link I've provided before.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!