This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Hinzufügen von Google Auth ohne ASPA.-NET-Identitätsdatenbank
Monday, 05 August 2024
Einleitung
In dieser App wollte ich einen einfachen Mechanismus der Anmeldung hinzufügen, um Kommentare hinzuzufügen.( und einige Admin-Aufgaben...). zur App hinzufügen... Ich wollte Google Auth für diesen Zweck verwenden.MSC3. Ich habe nicht die ASPC..NET Identity-Datenbank zu diesem Zweck nutzen wollen.MSZ5. Ich möchte die App so einfach wie möglich halten.
Datenbanken sind ein leistungsfähiger Bestandteil jeder Anwendung, aber sie fügen auch Komplexität hinzu... Ich wollte diese Komplexität vermeiden, bis ich es wirklich brauchte.
Schritte
Zuerst müssen Sie Google Auth in der Google Developer Console einrichten. Verknüpfung um Ihre Daten für Sie eingestellt Google Client ID und Secret-.
Sobald Sie Ihre Google-Client-ID und geheim haben, können Sie sie zu Ihren Appsettings hinzufügen.
"Auth" :{
"GoogleClientId": "",
"GoogleClientSecret": ""
}
WIE auch immer du diese nicht überprüfen solltest, um die Kontrolle zu übernehmen.Stattdessen kannst du für lokale Entwicklung die Secrets-Datei verwenden.

Dort können Sie Ihre Google Client-ID und Secret hinzufügen.Beachten Sie, dass Ihr Client Id tatsächlich vertraulich ist.
"Auth" :{
"GoogleClientId": "ID",
"GoogleClientSecret": "CLIENTSECRET"
}
Google Auth mit POCO konfigurieren
Anmerkung: Ich verwende eine modifizierte Version von Steve Smith-'s IConfigSection-Version, die kürzlich von Phil Haack berühmt gemacht wurde. Dies ist, um die IOptions Sachen zu vermeiden, die ich ein wenig klobig finde -( und selten brauchen, da ich fast nie ändern Konfiguration nach der Bereitstellung in meinen Szenarien-MSC1
In meinem tue ich dies, was mir erlaubt, den Abschnitt Namen von der Klasse selbst zu erhalten.
Click to expand
namespace Mostlylucid.Config;
public static class ConfigExtensions {
public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration)
where TConfig : class, new() {
if (services == null) throw new ArgumentNullException(nameof(services));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
var config = new TConfig();
configuration.Bind(config);
services.AddSingleton(config);
return config;
}
public static TConfig Configure<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var services = builder.Services;
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
return services.ConfigurePOCO<TConfig>(configuration.GetSection(sectionName));
}
public static TConfig GetConfig<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
var section = configuration.GetSection(sectionName).Get<TConfig>();
return section;
}
public static Dictionary<string, object> GetConfigSection(this IConfiguration configuration, string sectionName) {
var section = configuration.GetSection(sectionName);
var result = new Dictionary<string, object>();
foreach (var child in section.GetChildren()) {
var key = child.Key;
var value = child.Value;
result.Add(key, value);
}
return result;
}
public static Dictionary<string, object> GetConfigSection<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
return configuration.GetConfigSection(sectionName);
}
}
public interface IConfigSection {
public static abstract string Section { get; }
}
public class Auth : IConfigSection
{
public static string Section => "Auth";
public string GoogleClientId { get; set; }
public string GoogleClientSecret { get; set; }
public string AdminUserGoogleId { get; set; }
}
Wo ich eine statische Schnittstelle-Methode verwenden, um den Abschnitt Namen zu erhalten.
Dann in meinem Startup kann ich dies tun
var auth = builder.GetConfig<Auth>();
ANYWAY zurück zu den Google-Sachen
Programm einrichten
UM dies tatsächlich hinzuzufügen
services.AddCors(options =>
{
options.AddPolicy("AllowMostlylucid",
builder =>
{
builder.WithOrigins("https://www.mostlylucid.net")
.WithOrigins("https://mostlylucid.net")
.WithOrigins("https://localhost:7240")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{
options.ClientId = auth.GoogleClientId;
options.ClientSecret = auth.GoogleClientSecret;
});
Sie müssen auch diese in der Google-Identitätskonsole einrichten

Dies stellt sicher, dass der Google Auth nur von den Domains verwendet werden kann, die Sie angeben.
Google Auth In Razor
In meinem _Layout-.Cshtml Ich habe dieses Javascript-M,. Hier stelle ich meine Google Buttons ein und löse einen Rückruf aus, der die ASP-MSA-App protokolliert.
Google JS
<script src="https://accounts.google.com/gsi/client" async defer></script>
Dies ist der Dlow für den Code unten
function renderButton(element)
{
google.accounts.id.renderButton(
element,
{
type: "standard",
size: "large",
width: 200,
theme: "filled_black",
text: "sign_in_with",
shape: "rectangular",
logo_alignment: "left"
}
);
}
function initGoogleSignIn() {
google.accounts.id.initialize({
client_id: "839055275161-u7dqn2oco2729n6i5mk0fe7gap0bmg6g.apps.googleusercontent.com",
callback: handleCredentialResponse
});
const element = document.getElementById('google_button');
if (element) {
renderButton(element);
}
const secondElement = document.getElementById('google_button2');
if (secondElement) {
renderButton(secondElement);
}
}
function handleCredentialResponse(response) {
if (response.credential) {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/login', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (xhr.status === 200) {
window.location.reload();
} else {
console.error('Failed to log in.');
}
};
xhr.send(JSON.stringify({ idToken: response.credential }));
} else {
console.error('No credential in response.');
}
}
window.onload = initGoogleSignIn;
Hier können Sie sehen, dass ich bis zu zwei div Elemente in der Seite mit dem id google--Button und googles--button-2.-Dies sind die Elemente, die die Google JS rendern wird die Tasten in...
TIPP-:. Wenn Sie Tailwind verwenden, können Sie die Taste div shink, um im dunklen Modus korrekt zu arbeiten.Übrigens gibt es einen weißen Hintergrund rund um den Button wieder.
<div class="w-[200px] h-[39px] overflow-hidden rounded">
<div id="google_button">
</div>
</div>
Im obigen JavaScript poste ich dies zurück zu einer Controller-Aktion namens Login-.. Hier handle ich mit dem Google Auth...
const xhr = new XMLHttpRequest();
xhr.open('POST', '/login', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (xhr.status === 200) {
window.location.reload();
} else {
console.error('Failed to log in.');
}
};
xhr.send(JSON.stringify({ idToken: response.credential }));
Google Auth im Controller
Der Controller ist hier.'... es ist ziemlich einfach, es nimmt nur die geposteten JWT.MSC2 encodiert es dann verwendet, dass um sich bei der App zu anmelden.
[Route("login")]
[HttpPost]
public async Task<IActionResult> HandleGoogleCallback([FromBody] GoogleLoginRequest request)
{
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(request.IdToken) as JwtSecurityToken;
if (jsonToken == null)
{
return BadRequest("Invalid token");
}
var claimsIdentity = new ClaimsIdentity(
jsonToken.Claims,
GoogleDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
IsPersistent = true
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
return Ok();
}
}
HINWEIS:-Dies ist der Präfekt von ', da er die Claimnamen auflöst. Sie sind alle unteren Fall, aber es funktioniert für jetzt.
Controller Basisklasse zum Extrahieren der Login-Eigenschaften
In meinem BaseController extrahiere ich die Eigenschaften, die ich benötige
public record LoginData(bool loggedIn, string? name, string? avatarUrl, string? identifier);
protected LoginData GetUserInfo()
{
var authenticateResult = HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme).Result;
if (authenticateResult.Succeeded)
{
var principal = authenticateResult.Principal;
if(principal == null)
{
return new LoginData(false, null, null, null);
}
var name = principal.FindFirst("name").Value;
var avatarUrl =principal.FindFirst("picture").Value;
var nameIdentifier = principal.FindFirst("sub");
return new LoginData(true, name, avatarUrl, nameIdentifier?.Value);
}
return new LoginData(false,null,null,null);
}
Und dies ermöglicht es, Gooogle-Authentifizierung zu verwenden, ohne die ASP.....NET Identity-Datenbank zu benutzen.