This article describes how user login authentication is implemented in Blazor Static Server Side Presentation (Static SSR) mode.
1. Introduction to SSR
SSR is server-side rendering, where HTML is generated by the Core runtime on the server and sent over the network to the client for display in the client's browser.There are two types of SSR:
- Static SSR: The server generates static HTML, which does not provide user interactivity or maintain Razor component state, and communicates via the HTTP protocol.
- Interactive SSR: Blazor events allow user interaction and Razor component state is maintained by the Blazor framework, communicating via SignalR connections using the WebSocket protocol.
2. Why static SSRs?
Since interactive SSR has the problem of disconnection and reconnection, which affects the user experience, static SSR components are used to present the server-side content, and JavaScript is used as the front-end interaction in order to increase the front-end interaction experience.
3. Ideas for realization
- HttpContext object with cascading parameters in a file to get whether the user is logged in or not
- passes the user login information to the cascading Context object of the routing component.
- Get user information in all subcomponents using a Context object with cascading parameters
- Logging in and logging out is accomplished using and
4. Steps towards realization
- Create UserInfo and Context classes
public class UserInfo
{
public string UserName { get; set; }
}
public class Context
{
public UserInfo CurrentUser { get; set; }
}
- Create File
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<Routes User="user" />
</body>
</html>
@code {
[CascadingParameter] private HttpContext HttpContext { get; set; }
private UserInfo user;
protected override void OnInitialized()
{
();
if ()
user = new UserInfo { UserName = };
else
user = null;
}
}
- Create File
<CascadingValue Value="context" IsFixed>
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" />
</Found>
<NotFound></NotFound>
</Router>
</CascadingValue>
@code {
private UIContext context;
[Parameter] public UserInfo User { get; set; }
protected override void OnInitialized()
{
context = new Context();
= User;
();
}
}
- Create File
@if ( == null)
{
<span onclick="login()">log in</span>
<script>
function login() { fetch('/signin').then(res => ()); }
</script>
}
else
{
<span onclick="logout()">abort</span>
<script>
function logout() { fetch('/signout').then(res => ()); }
</script>
}
@code {
[CascadingParameter] private Context Context { get; set; }
}
- Create File
public class AuthController : ControllerBase
{
private const string AuthType = "App_Cookie";
[Route("signin")]
public async Task Login([FromBody] UserInfo info)
{
var claims = new List<Claim>() { new(, ) };
var identity = new ClaimsIdentity(claims, AuthType);
var principal = new ClaimsPrincipal(identity);
await (AuthType, principal);
}
[Route("signout")]
public async Task Logout()
{
await (AuthType);
}
}