C# 能够存储在IHttpContextAccessor.HttpContext.Session中-检索为空
我正在使用一个API,并使用.NETCore2.1中的会话功能和标准依赖项注入来存储和检索会话存储中的值。我的问题是,我能够设置字符串值并将其存储到Session.store中,但是当我尝试在另一个方法中检索这些值时,存储是空的 下面是我的Startup.cs为DI设置IHttpContextAccessor并启用会话存储C# 能够存储在IHttpContextAccessor.HttpContext.Session中-检索为空,c#,session,asp.net-core,C#,Session,Asp.net Core,我正在使用一个API,并使用.NETCore2.1中的会话功能和标准依赖项注入来存储和检索会话存储中的值。我的问题是,我能够设置字符串值并将其存储到Session.store中,但是当我尝试在另一个方法中检索这些值时,存储是空的 下面是我的Startup.cs为DI设置IHttpContextAccessor并启用会话存储 public void ConfigureServices(IServiceCollection services) { services.Confi
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non- // essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// Configure app settings to inject in other classes.
services.AddOptions();
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
// Services to be injected.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationService, AuthenticationService>();
services.AddSingleton<IConstituentsService, ConstituentsService>();
services.AddSingleton<ISessionService, SessionService>();
// Add MVC.
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// Configure session.
services.AddMemoryCache();
services.AddDistributedMemoryCache();
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.Name = ".AuthCodeFlowTutorial.Session";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
您在哪里以及如何使用ISessionService?您的意思是什么?我在上面的类中使用它,这是接口中列出的四个方法的实现。我的意思是在哪里注入
ISessionService
并调用GetAccessToken
或SetTokens
。你可能会在没有HTTP上下文的时候调用它SetTokens()
为AuthenticationService
调用,该服务也在Startup.cs
中设置,并在AuthenticationController
中用于加载初始页面。所以HTTP上下文应该在那个时候就已经完全设置好了TryGetString()
在SessionService
中调用,而不是在其他地方调用。因此,如果我能够在调用TrGetString()
之前成功地将值存储在SessionService
中,那么值应该在那里。您在哪里调用GetAccessToken
?
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
namespace CHS.SkyApiAuthCodeFlow
{
/// <summary>
/// Sets, gets, and destroys session variables.
/// </summary>
public class SessionService : ISessionService
{
private const string ACCESS_TOKEN_NAME = "token";
private const string REFRESH_TOKEN_NAME = "refreshToken";
private readonly IHttpContextAccessor _httpContextAccessor;
public SessionService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <summary>
/// Destroys access and refresh tokens from the session.
/// </summary>
public void ClearTokens()
{
try
{
_httpContextAccessor.HttpContext.Session.Remove(ACCESS_TOKEN_NAME);
_httpContextAccessor.HttpContext.Session.Remove(REFRESH_TOKEN_NAME);
}
catch (Exception error)
{
Console.WriteLine("LOGOUT ERROR: " + error.Message);
}
}
/// <summary>
/// Return access token, if saved, or an empty string.
/// </summary>
public string GetAccessToken()
{
return TryGetString(ACCESS_TOKEN_NAME);
}
/// <summary>
/// Return refresh token, if saved, or an empty string.
/// </summary>
public string GetRefreshToken()
{
return TryGetString(REFRESH_TOKEN_NAME);
}
/// <summary>
/// Sets the access and refresh tokens based on an HTTP response.
/// </summary>
public void SetTokens(HttpResponseMessage response)
{
if (response.IsSuccessStatusCode)
{
string jsonString = response.Content.ReadAsStringAsync().Result;
Dictionary<string, string> attrs = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
_httpContextAccessor.HttpContext.Session.SetString(ACCESS_TOKEN_NAME, attrs["access_token"]);
_httpContextAccessor.HttpContext.Session.SetString(REFRESH_TOKEN_NAME, attrs["refresh_token"]);
}
}
/// <summary>
/// Return session value as a string (if it exists), or an empty string.
/// </summary>
private string TryGetString(string name)
{
byte[] valueBytes = new Byte[700];
bool valueOkay = _httpContextAccessor.HttpContext.Session.TryGetValue(name, out valueBytes);
if (valueOkay)
{
return System.Text.Encoding.UTF8.GetString(valueBytes);
}
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Extensions.Options;
namespace CHS.SkyApiAuthCodeFlow
{
/// <summary>
/// Contains business logic and helper methods that interact with the authentication provider.
/// </summary>
public class AuthenticationService : IAuthenticationService
{
private readonly IOptions<AppSettings> _appSettings;
private ISessionService _sessionService;
public AuthenticationService(IOptions<AppSettings> appSettings, ISessionService sessionService)
{
_appSettings = appSettings;
_sessionService = sessionService;
}
/// <summary>
/// Fetches access/refresh tokens from the provider.
/// <param name="requestBody">Key-value attributes to be sent with the request.</param>
/// <returns>The response from the provider.</returns>
/// </summary>
private HttpResponseMessage FetchTokens(Dictionary<string, string> requestBody)
{
using (HttpClient client = new HttpClient())
{
// Build token endpoint URL.
string url = new Uri(new Uri(_appSettings.Value.AuthBaseUri), "token").ToString();
// Set request headers.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
client.DefaultRequestHeaders.TryAddWithoutValidation(
"Authorization", "Basic " + Base64Encode(_appSettings.Value.AuthClientId + ":" + _appSettings.Value.AuthClientSecret));
// Fetch tokens from auth server.
HttpResponseMessage response = client.PostAsync(url, new FormUrlEncodedContent(requestBody)).Result;
// Save the access/refresh tokens in the Session.
_sessionService.SetTokens(response);
return response;
}
}
/// <summary>
/// Fetches a new set of access/refresh tokens (from an authorization code).
/// <param name="code">The authorization code contained within the provider's authorization response.</param>
/// </summary>
public HttpResponseMessage ExchangeCodeForAccessToken(string code)
{
return FetchTokens(new Dictionary<string, string>(){
{ "code", code },
{ "grant_type", "authorization_code" },
{ "redirect_uri", _appSettings.Value.AuthRedirectUri }
});
}
/// <summary>
/// Refreshes the expired access token (from the refresh token stored in the session).
/// </summary>
public HttpResponseMessage RefreshAccessToken()
{
return FetchTokens(new Dictionary<string, string>(){
{ "grant_type", "refresh_token" },
{ "refresh_token", _sessionService.GetRefreshToken() }
});
}
/// <summary>
/// Builds and returns a string representative of the provider's authorization URI.
/// </summary>
public Uri GetAuthorizationUri()
{
return new Uri(
new Uri(_appSettings.Value.AuthBaseUri), "authorization" +
"?client_id=" + _appSettings.Value.AuthClientId +
"&response_type=code" +
"&redirect_uri=" + _appSettings.Value.AuthRedirectUri
);
}
/// <summary>
/// Determines if the session contains an access token.
/// </summary>
public bool IsAuthenticated()
{
return (_sessionService.GetAccessToken() != null);
}
/// <summary>
/// Destroys the access/refresh tokens stored in the session.
/// </summary>
public void LogOut()
{
_sessionService.ClearTokens();
}
/// <summary>
/// Encodes a string as Base64.
/// </summary>
private static string Base64Encode(string plainText)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(bytes);
}
}
}