ファイルアクセス許可を制御するためのカスタム認証を作成するには、次の手順を実行します。
下の画像に示すように、アプリケーションのフォルダにアクセスできるロールを定義するファイルを追加する必要があります。 _rolesファイルを追加すると、承認属性でロール情報を読み取ることができます。
ユーザーに割り当てられた役割に基づいてフォルダへのアクセス権限を付与するには、認証属性の役割情報を参照してください。認証属性はユーザーのログイン情報を識別し、ユーザーに割り当てられた役割に基づいてファイルへのアクセスを提供します。
StorageAuthorizeAttribute.cs |
コードのコピー
|
---|---|
using C1.Web.Api.Report; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Web.Http.Controllers; using System.Web.Http.Filters; using C1.Web.Api.Storage; namespace SalesReport.Controllers { internal class StorageAuthorizeAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { var principal = actionContext.ControllerContext.RequestContext.Principal; if (principal == null || principal.Identity == null || !principal.Identity.IsAuthenticated) { Unauthorize(actionContext); return; } var values = actionContext.RequestContext.RouteData.Values; object pathObj; if (!values.TryGetValue("path", out pathObj)) { return; } var path = (pathObj as string) ?? string.Empty; var defaultProvider = ReportProviderManager.Current.Get("") as FlexReportProvider; if (defaultProvider == null) { return; } var roles = GetRoles(defaultProvider.Storage, path); if(!roles.Any()) { return; } if (!roles.Any(r => principal.IsInRole(r))) { Unauthorize(actionContext); } } private static readonly object _locker = new object(); private static readonly IDictionary<string, IEnumerable<string>> _folderRoles = new Dictionary<string, IEnumerable<string>> (StringComparer.OrdinalIgnoreCase); private static IEnumerable<string> GetRoles (IStorageProvider storage, string path) { string folder = path; var fileStorage = storage.GetFileStorage(path); if (fileStorage.Exists) { var pathParts = path.Split('/'); pathParts = pathParts.Take(pathParts.Length - 1).ToArray(); folder = string.Join("/", pathParts); } lock (_locker) { IEnumerable<string> roles; if (_folderRoles.TryGetValue(folder, out roles)) { return roles; } var roleList = GetFolderRoles("", storage); var folderParts = folder.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var currentFolder = ""; foreach (var part in folderParts) { currentFolder += part; var current = GetFolderRoles(currentFolder, storage); if(current != null && current.Any()) { roleList = current; } currentFolder += "/"; } return roleList; } } private static IEnumerable<string> GetFolderRoles(string path, IStorageProvider storage) { IEnumerable<string> roles; if (_folderRoles.TryGetValue(path, out roles)) { return roles; } var roleList = new List<string>(); var rolesFile = storage.GetFileStorage(path + "/_.roles"); if(rolesFile.Exists) { using (var reader = new StreamReader(rolesFile.Read())) { while (!reader.EndOfStream) { var line = reader.ReadLine(); if (!string.IsNullOrEmpty(line)) { roleList.Add(line); } } } } _folderRoles.Add(path, roleList); return roleList; } private static void Unauthorize(HttpActionContext actionContext) { actionContext.Response = new System.Net.Http. HttpResponseMessage(HttpStatusCode.Unauthorized); } } } |
ReportController
)。ReportController.cs |
コードのコピー
|
---|---|
using System.Web.Http; namespace SalesReport.Controllers { public class ReportController : C1.Web.Api.Report.ReportController { [StorageAuthorize] public override IHttpActionResult GetCatalogInfo(string path, bool recursive = false) { return base.GetCatalogInfo(path, recursive); } } } |
CustomDirectRouteProvider.cs |
コードのコピー
|
---|---|
using System.Collections.Generic; using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Routing; namespace SalesReport { public class CustomDirectRouteProvider : DefaultDirectRouteProvider { protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { // ベースクラスコントローラのアクションで設定されたルート属性を継承します return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(true); } protected override string GetRoutePrefix(HttpControllerDescriptor controllerDescriptor) { var prefix = base.GetRoutePrefix(controllerDescriptor); if (string.IsNullOrEmpty(prefix)) { var prefixAttr = controllerDescriptor.GetCustomAttributes <IRoutePrefix>(true).FirstOrDefault(); if (prefixAttr != null) { return prefixAttr.Prefix; } } return prefix; } } } |
このアプリケーションには2つのReportControllerが用意されています。以下のコードを使用すると、クライアントアプリケーションによって必要なReportControllerを識別するためのカスタマイズされたIHttpControllerTypeResolverが追加されます。
CustomDirectRouteProvider.cs |
コードのコピー
|
---|---|
using System.Collections.Generic; using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Routing; namespace SalesReport { public class CustomDirectRouteProvider : DefaultDirectRouteProvider { protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { // ベースクラスコントローラのアクションで装飾されたルート属性を継承する return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(true); } protected override string GetRoutePrefix(HttpControllerDescriptor controllerDescriptor) { var prefix = base.GetRoutePrefix(controllerDescriptor); if (string.IsNullOrEmpty(prefix)) { var prefixAttr = controllerDescriptor.GetCustomAttributes<IRoutePrefix>(true).FirstOrDefault(); if (prefixAttr != null) { return prefixAttr.Prefix; } } return prefix; } } } |
WebApiConfig.csファイルにHttpConfigurationを登録します。 また、ベアラートークン認証のみを使用するようにWeb APIを構成します。
WebApiConfig.cs |
コードのコピー
|
---|---|
using System.Web.Http; using Microsoft.Owin.Security.OAuth; using System.Web.Http.Dispatcher; namespace SalesReport { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web APIの設定とサービス // ベアラートークン認証のみを使用するようにWeb APIを構成します config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API ルート config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Services.Replace(typeof(IHttpControllerTypeResolver), new ReportsControllerTypeResolver()); } } |