ASP.NET Web APIを使用したセッションへのアクセス


268

セッションとRESTが正確に連動していないことに気付きましたが、新しいWeb APIを使用してセッション状態にアクセスすることはできませんか?HttpContext.Current.Session常にnullです。


4
[SessionState(SessionStateBehavior.Required)]上のApiControllerトリック(または行い.ReadOnly、適切な場合)。
ローマスターコフ2018年

@RomanStarkovこれを機能させることができませんでした。どの環境を使用しましたか?.NET Core?
Bondolin

@Bondolinいいえ、これはコアではありませんでした。
ロマン・スターコフ

@RomanStarkov MVCでは?見つけられません。
Bondolin

@Bondolin SessionStateAttributeとはい、MVC。
Roman Starkov

回答:


336

MVC

MVCプロジェクトの場合は、次の変更を行います(WebFormsとDot Net Coreは以下で回答)。

WebApiConfig.cs

public static class WebApiConfig
{
    public static string UrlPrefix         { get { return "api"; } }
    public static string UrlPrefixRelative { get { return "~/api"; } }

    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    ...

    protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    private bool IsWebApiRequest()
    {
        return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
    }

}

このソリューションには、AJAX呼び出しを行うためにJavaScriptでベースURLをフェッチできるという追加のボーナスがあります。

_Layout.cshtml

<body>
    @RenderBody()

    <script type="text/javascript">
        var apiBaseUrl = '@Url.Content(ProjectNameSpace.WebApiConfig.UrlPrefixRelative)';
    </script>

    @RenderSection("scripts", required: false) 

次に、JavaScriptファイル/コード内で、セッションにアクセスできるwebapi呼び出しを実行できます。

$.getJSON(apiBaseUrl + '/MyApi')
   .done(function (data) {
       alert('session data received: ' + data.whatever);
   })
);

WebForms

上記を実行しますが、代わりにRouteCollectionを取得するようにWebApiConfig.Register関数を変更します。

public static void Register(RouteCollection routes)
{
    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: WebApiConfig.UrlPrefix + "/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

そして、Application_Startで以下を呼び出します。

WebApiConfig.Register(RouteTable.Routes);

ドットネットコア

Microsoft.AspNetCore.Session NuGetパッケージを追加して、次のコードを変更します。

Startup.cs

コールAddDistributedMemoryCacheAddSession機能ConfigureServices内のサービスオブジェクトのメソッドを:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    ...

    services.AddDistributedMemoryCache();
    services.AddSession();

そして、Configure関数にUseSessionへの呼び出しを追加します。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
    app.UseSession();
    app.UseMvc();

SessionController.cs

コントローラ内で、先頭にusingステートメントを追加します。

using Microsoft.AspNetCore.Http;

次に、次のようにコード内でHttpContext.Sessionオブジェクトを使用します。

    [HttpGet("set/{data}")]
    public IActionResult setsession(string data)
    {
        HttpContext.Session.SetString("keyname", data);
        return Ok("session data set");
    }

    [HttpGet("get")]
    public IActionResult getsessiondata()
    {
        var sessionData = HttpContext.Session.GetString("keyname");
        return Ok(sessionData);
    }

これでヒットできるはずです:

http://localhost:1234/api/session/set/thisissomedata

そして、このURLに行くと、それが引き出されます:

http://localhost:1234/api/session/get

ドットネットコア内のセッションデータへのアクセスに関する詳細については、https//docs.microsoft.com/en-us/aspnet/core/fundamentals/app-stateをご覧ください。

パフォーマンスの懸念

パフォーマンスに関する下記のSimon Weaverの回答を読んでください。WebApiプロジェクト内のセッションデータにアクセスしている場合は、パフォーマンスに非常に深刻な影響を与える可能性があります。ASP.NETが同時リクエストに200ミリ秒の遅延を強制するのを見ました。これは、多くの同時リクエストがある場合に、合計して悲惨になる可能性があります。


セキュリティ上の懸念

ユーザーごとにリソースをロックダウンしていることを確認してください。認証されたユーザーは、アクセスできないWebApiからデータを取得できません。

ASP.NET Web APIでの認証と承認に関するMicrosoftの記事をお読みください-https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

Cross-Site Request Forgeryハック攻撃の回避に関するMicrosoftの記事を読んでください。(要するに、AntiForgery.Validateメソッドを確認してください)-https://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks


7
完璧です。シンプルで機能します。MVC以外の場合は、Application_PostAuthorizeRequest()をGlobal.ascx.csに追加するだけです。
mhenry1384 2014

1
@JCallicoに感謝します。ほとんどの人が最初にASP.NETページにアクセスしてセッションを作成したと思います。
Rocklan、2014年

3
パスがWebApiConfig.UrlPrefixおよびWebApiConfig.UrlPrefixRelativeで始まる場所でもtrueを返すようにIsWebApiRequest()を変更する必要がありました。それ以外は、期待どおりに動作します。
gb2d 2015年

7
この修正に関して言及すべきことが1つあります。SessionStateBehaviorをRequiredに設定すると、すべてのリクエストがセッションオブジェクトのロックのために同期して実行されるため、webapiがボトルネックになります。代わりに、SessionStateBehavior.Readonlyとして実行することもできます。この方法では、セッションオブジェクトにロックは作成されません。
Michael Kire Hansen

2
セッション状態の動作を「必須」に設定するときは注意してください。書き込み権限を持つリクエストはセッションをロックし、クライアントごとに複数のHttpApplicationsが生成されるのを防ぎます。ルートごとにセッション状態を適切なレベルに設定する必要があります。ここで私の答えを参照してください:stackoverflow.com/a/34727708/1412787
Axel Wilczek

66

カスタムRouteHandlerを使用してセッション状態にアクセスできます。

// In global.asax
public class MvcApp : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        var route = routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        route.RouteHandler = new MyHttpControllerRouteHandler();
    }
}

// Create two new classes
public class MyHttpControllerHandler
    : HttpControllerHandler, IRequiresSessionState
{
    public MyHttpControllerHandler(RouteData routeData) : base(routeData)
    { }
}
public class MyHttpControllerRouteHandler : HttpControllerRouteHandler
{
    protected override IHttpHandler GetHttpHandler(
        RequestContext requestContext)
    {
        return new MyHttpControllerHandler(requestContext.RouteData);
    }
}

// Now Session is visible in your Web API
public class ValuesController : ApiController
{
    public string Get(string input)
    {
        var session = HttpContext.Current.Session;
        if (session != null)
        {
            if (session["Time"] == null)
                session["Time"] = DateTime.Now;
            return "Session Time: " + session["Time"] + input;
        }
        return "Session is not availabe" + input;
    }
}

ここにあります:http : //techhasnoboundary.blogspot.com/2012/03/mvc-4-web-api-access-session.html


14
更新:API関数がセッションから読み取り、セッションを変更しない場合は、IRequiresSessionStateではなくIReadOnlySessionStateを使用することをお勧めします。これにより、API関数の処理中にセッションがロックされなくなります。
warrickh 2013年

6
MVC 4で私のために働いていません-route.RouteHandlerは私にとってもプロパティではありません。@LachlanBは私にとってはうまくいったようです。
bkwdesign 2013

3
MVCソリューションを指摘してくれた@bkwdesignに感謝します。この回答はWeb APIのみに関連しています。
warrickh 2013

2
これはルート属性をサポートしていないようです。考え?
Tim S

bkwdesignが指摘したように、これはサポートされなくなりました。ただし、DataTokensを使用してルートごとにセッション状態の動作を定義する方法があります:stackoverflow.com/a/34727708/1412787
Axel Wilczek

46

WebAPIでセッションの使用を回避する理由

パフォーマンス、パフォーマンス、パフォーマンス!

WebAPIでSessionを使用してはならない理由は、よく見逃されがちです。

セッションの使用中にASP.NETが機能する方法は、単一のクライアントから受信したすべての要求シリアル化することです。ここで私はオブジェクトのシリアル化について話しているのではなく、受け取った順に実行し、それぞれが完了するのを待ってから次の実行を開始します。これは、2つのリクエストがそれぞれセッションに同時にアクセスしようとした場合に、厄介なスレッド/競合状態を回避するためです。

同時リクエストとセッション状態

ASP.NETセッション状態へのアクセスはセッションごとに排他的です。つまり、2人の異なるユーザーが同時に要求を行うと、別々の各セッションへのアクセスが同時に許可されます。ただし、同じセッションに対して(同じSessionID値を使用して)2つの同時要求が行われた場合、最初の要求はセッション情報への排他的アクセスを取得します。2番目の要求は、最初の要求が完了した後にのみ実行されます。(最初の要求がロックのタイムアウトを超えたために情報の排他ロックが解放された場合、2番目のセッションもアクセスできます。)@ PageディレクティブのEnableSessionState値がReadOnlyに設定されている場合、読み取り専用の要求セッション情報によって、セッションデータが排他的にロックされることはありません。ただし、セッションデータの読み取り専用要求は、セッションデータの読み取り/書き込み要求によって設定されたロックがクリアされるまで待機する必要がある場合があります。

では、これはWeb APIにとって何を意味するのでしょうか。多くのAJAXリクエストを実行しているアプリケーションがある場合、一度に実行できるのは1つだけです。遅いリクエストがある場合は、完了するまでそのクライアントからの他のすべてをブロックします。一部のアプリケーションでは、これによりパフォーマンスが著しく遅くなる可能性があります。

したがって、ユーザーセッションから何かが絶対に必要な場合は、おそらくMVCコントローラーを使用し、WebApiで有効にすることによる不必要なパフォーマンスの低下を回避する必要があります。

Thread.Sleep(5000)WebAPIメソッドを入力してセッションを有効にするだけで、これを自分で簡単にテストできます。リクエストを5回実行すると、完了するまでに合計25秒かかります。セッションがない場合、合計で5秒強かかります。

(これと同じ理由がSignalRにも当てはまります)。


18
メソッドがセッションからのみ読み取る場合は、[SessionState(SessionStateBehavior.ReadOnly)]を使用してこれを回避できます。
ロックラン、2015

21

そうですね、RESTはステートレスです。セッションを使用する場合、処理はステートフルになり、後続のリクエストは(セッションからの)状態を使用できます。

セッションを元に戻すには、状態を関連付けるためのキーを提供する必要があります。通常のasp.netアプリケーションでは、そのキーはcookie(cookie-sessions)またはurlパラメーター(cookielessセッション)を使用して提供されます。

残りのセッションを忘れるセッションが必要な場合、セッションはRESTベースの設計では無関係です。検証のためのセッションが必要な場合は、トークンを使用するか、IPアドレスで認証します。


10
これについてはよくわかりません。Microsoftの例では、Authorize属性の使用を示しています。私はそれを試してみましたが、フォームベース認証で動作します。Web APIは、デフォルトの認証Cookieで渡される認証状態を認識しています。
マーク

4
これが私が参照しているサンプルcode.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7です。新しいRESTベースのWeb APIを使用して、フォーム認証を実装します。
マーク

4
セッション状態を必要とせずに[Authorize]属性を正常に使用しました。IDを設定するための認証メッセージハンドラーを作成しました。
アントニースコット

57
彼の問題に対する答えを提供しなかったためにあなたを不評にした、そしてそれ以上に、Web APIはajaxの重いWebアプリでうまく機能する非同期フレームワークです。Web APIフレームワークの使用から利益を得るには、RESTful設計のすべての要素を尊重する必要があるとは誰も言っていません。
ブライアンオグデン

3
@MarkS。Web APIがセッション状態を認識していないことを通知する権利です。否定的な答えはまだ答えのままです。賛成票。
アントワーヌメルツハイム2014年

20

マーク、オタクのMVCサンプルを確認すると、ロジックはほとんど同じです。

Cookieを取得して現在のセッションで設定するだけです。

Global.asax.cs

public override void Init()
{
    this.AuthenticateRequest += new EventHandler(WebApiApplication_AuthenticateRequest);
    base.Init();
}

void WebApiApplication_AuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

    SampleIdentity id = new SampleIdentity(ticket);
    GenericPrincipal prin = new GenericPrincipal(id, null); 

    HttpContext.Current.User = prin;
}

enter code here

nerddinnerプロジェクトから借用できる「SampleIdentity」クラスを定義する必要があります。


IDクラスはNerdDinner_2.0 \ NerdDinner \ Models \ NerdIdentity.csにあります。
mhenry1384 2014

これは私には機能しません(.NET 4の場合)。私はそのクッキーを持っていません。FormsAuthenticationをオンにしている場合にのみ機能しますか?
mhenry1384 2014

ログインフォームを介して認証した後、Cookieは確かに生成されます。また、どのように/それが作成された時にカスタマイズ見ることができましたstackoverflow.com/questions/7217105をしかし、あなたはまだ効果的にWebサーバに対して認証するユーザーを必要とする
JSancho

質問はHttpContext.Current.Sessionを要求し、この回答は何をする必要があるか明確に説明していません。@LachlanBの回答を参照してください。
JCallico 14

14

問題を修正するには:

protected void Application_PostAuthorizeRequest()
{
    System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
}

Global.asax.cs


4
警告!これにより、すべてのリクエストのセッションが有効になります。アプリケーションが埋め込みリソースを使用している場合、これはパフォーマンスを本当に低下させる可能性があります。
cgatian 2015

@cgatian代替ソリューションは修正されましたか?
Kiquenet 2016年

最良のアプローチは@Treyphorが提案するものだと思います。すべてのリクエストに対して有効にしないでください。URLに「/ api」または何かが含まれるルートのみ。また、可能であれば、APIコントローラーの読み取り専用にセッション状態を設定します。
cgatian 2016年

10

最後の1つは現在機能していません。これを1つ選択してください。

App_StartのWebApiConfig.cs内

    public static string _WebApiExecutionPath = "api";

    public static void Register(HttpConfiguration config)
    {
        var basicRouteTemplate = string.Format("{0}/{1}", _WebApiExecutionPath, "{controller}");

        // Controller Only
        // To handle routes like `/api/VTRouting`
        config.Routes.MapHttpRoute(
            name: "ControllerOnly",
            routeTemplate: basicRouteTemplate//"{0}/{controller}"
        );

        // Controller with ID
        // To handle routes like `/api/VTRouting/1`
        config.Routes.MapHttpRoute(
            name: "ControllerAndId",
            routeTemplate: string.Format ("{0}/{1}", basicRouteTemplate, "{id}"),
            defaults: null,
            constraints: new { id = @"^\d+$" } // Only integers 
        );

Global.asax

protected void Application_PostAuthorizeRequest()
{
  if (IsWebApiRequest())
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

private static bool IsWebApiRequest()
{
  return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(_WebApiExecutionPath);
}

4番目:http ://forums.asp.net/t/1773026.aspx/1


これは最も簡単な解決策ですが、コードにいくつかの間違いがあるため、実際には機能しません。私はこれに基づいて別のソリューションを投稿しました。自由に編集して私のものに合わせてください。
ロックラン2013

_WebApiExecutionPath行のわずかな修正は、パブリック静的文字列_WebApiExecutionPath = "〜/ api"を読み取る必要があります。
スティーブンebichondo 2016年

8

LachlanBの回答に続き、ApiControllerが特定のディレクトリ(/ apiなど)内にない場合は、RouteTable.Routes.GetRouteDataを使用してリクエストをテストできます。次に例を示します。

protected void Application_PostAuthorizeRequest()
    {
        // WebApi SessionState
        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
        if (routeData != null && routeData.RouteHandler is HttpControllerRouteHandler)
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
    }

8

これと同じ問題がasp.net mvcにもありました。このメソッドを、すべてのAPIコントローラーが継承するベースAPIコントローラーにこのメソッドを配置することで修正しました。

    /// <summary>
    /// Get the session from HttpContext.Current, if that is null try to get it from the Request properties.
    /// </summary>
    /// <returns></returns>
    protected HttpContextWrapper GetHttpContextWrapper()
    {
      HttpContextWrapper httpContextWrapper = null;
      if (HttpContext.Current != null)
      {
        httpContextWrapper = new HttpContextWrapper(HttpContext.Current);
      }
      else if (Request.Properties.ContainsKey("MS_HttpContext"))
      {
        httpContextWrapper = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
      }
      return httpContextWrapper;
    }

次に、あなたが行うセッションにアクセスしたいあなたのAPI呼び出しで:

HttpContextWrapper httpContextWrapper = GetHttpContextWrapper();
var someVariableFromSession = httpContextWrapper.Session["SomeSessionValue"];

他の人が投稿したように、これも私のGlobal.asax.csファイルにありますが、上記の方法を使用してまだ必要かどうかはわかりませんが、ここでは念のため説明します。

/// <summary>
/// The following method makes Session available.
/// </summary>
protected void Application_PostAuthorizeRequest()
{
  if (HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith("~/api"))
  {
    HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
  }
}

セッションが必要なapi呼び出しに固執できるカスタムフィルター属性を作成することもできます。その後、HttpContext.Current.Session ["SomeValue"]を介して通常行うように、api呼び出しでセッションを使用できます。

  /// <summary>
  /// Filter that gets session context from request if HttpContext.Current is null.
  /// </summary>
  public class RequireSessionAttribute : ActionFilterAttribute
  {
    /// <summary>
    /// Runs before action
    /// </summary>
    /// <param name="actionContext"></param>
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
      if (HttpContext.Current == null)
      {
        if (actionContext.Request.Properties.ContainsKey("MS_HttpContext"))
        {
          HttpContext.Current = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).ApplicationInstance.Context;
        }
      }
    }
  }

お役に立てれば。


6

私は@LachlanBアプローチに従い、実際にセッションCookieがリクエストに存在するときにセッションを利用できました。不足している部分は、セッションCookieがクライアントに初めて送信される方法ですか?

HttpSessionStateの可用性を有効にするだけでなく、新しいセッションが作成されたときにCookieをクライアントに送信するHttpModuleを作成しました。

public class WebApiSessionModule : IHttpModule
{
    private static readonly string SessionStateCookieName = "ASP.NET_SessionId";

    public void Init(HttpApplication context)
    {
        context.PostAuthorizeRequest += this.OnPostAuthorizeRequest;
        context.PostRequestHandlerExecute += this.PostRequestHandlerExecute;
    }

    public void Dispose()
    {
    }

    protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            context.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

    protected virtual void PostRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (this.IsWebApiRequest(context))
        {
            this.AddSessionCookieToResponseIfNeeded(context);
        }
    }

    protected virtual void AddSessionCookieToResponseIfNeeded(HttpContext context)
    {
        HttpSessionState session = context.Session;

        if (session == null)
        {
            // session not available
            return;
        }

        if (!session.IsNewSession)
        {
            // it's safe to assume that the cookie was
            // received as part of the request so there is
            // no need to set it
            return;
        }

        string cookieName = GetSessionCookieName();
        HttpCookie cookie = context.Response.Cookies[cookieName];
        if (cookie == null || cookie.Value != session.SessionID)
        {
            context.Response.Cookies.Remove(cookieName);
            context.Response.Cookies.Add(new HttpCookie(cookieName, session.SessionID));
        }
    }

    protected virtual string GetSessionCookieName()
    {
        var sessionStateSection = (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");

        return sessionStateSection != null && !string.IsNullOrWhiteSpace(sessionStateSection.CookieName) ? sessionStateSection.CookieName : SessionStateCookieName;
    }

    protected virtual bool IsWebApiRequest(HttpContext context)
    {
        string requestPath = context.Request.AppRelativeCurrentExecutionFilePath;

        if (requestPath == null)
        {
            return false;
        }

        return requestPath.StartsWith(WebApiConfig.UrlPrefixRelative, StringComparison.InvariantCultureIgnoreCase);
    }
}

これはうまくいきます。これにより、タイムアウトしない限り、リクエスト間でセッションが同じに保たれます。セッション状態を「要求」と「読み取り専用」の間で切り替えてリクエストのブロックを停止するための良い方法を見つけるまで、製品でそれを使用するかどうかはまだわかりませんが、これで希望の開始パスが得られました。ありがとうございました!
デレックディーン

3

@LachlanBの回答で言及する必要があることが1つあります。

protected void Application_PostAuthorizeRequest()
    {
        if (IsWebApiRequest())
        {
            HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
        }
    }

行を省略した場合 if (IsWebApiRequest())

サイトがWebフォームページと混在している場合、サイト全体でページの読み込みが遅くなる問題があります。


0

はい、セッションはRest APIと連動しません。また、このプラクティスを回避する必要があります。しかし、要件ごとに、すべての要求でクライアントサーバーが状態またはデータを交換または維持できるように、セッションを何らかの方法で維持する必要があります。したがって、RESTプロトコルを壊すことなくこれを実現する最良の方法は、JWTのようなトークンを介して通信することです。

https://jwt.io/


-4

基本に戻り、単純にして、APIに渡す非表示のhtml値にセッション値を保存しませんか?

コントローラ

public ActionResult Index()
        {

            Session["Blah"] = 609;

            YourObject yourObject = new YourObject();
            yourObject.SessionValue = int.Parse(Session["Blah"].ToString());

            return View(yourObject);
        }

cshtml

@model YourObject

@{
    var sessionValue = Model.SessionValue;
}

<input type="hidden" value="@sessionValue" id="hBlah" />

JavaScript

$(document).ready(function(){

    var sessionValue = $('#hBlah').val();

    alert(sessionValue);

    /* Now call your API with the session variable */}

}


1
アプリケーションがMVCとWebAPIの両方を使用する場合はどうでしょうか?また、Sharepointセキュリティトークンなど、サーバー側に保存するほうが合理的です。Azure Blobコンテナーのようなトークンストレージ用の特別なラッパーを実装する代わりに、このタイプのデータのSessionを合理的に再利用する場合があります。アプリテンプレートに実装されているSharepointセキュリティコンテキストは、セッションを使用してこれらのセキュリティコンテキストを格納し、数キロバイトのデータではなく、転送される小さなデータ(セッションタグ)のみを保存します。これらのコンテキストが小さくなればそれは素晴らしいことです...
Konstantin Isaev 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.