了解如何在可将用户登录的 Web 应用的代码中添加登录。Learn how to add sign-in to the code for your web app that signs in users.然后了解如何让用户注销。Then, learn how to let them sign out.
登录Sign-in
登录由两个部分组成:Sign-in consists of two parts:
HTML 页中的登录按钮The sign-in button on the HTML page
控制器 code-behind 中的登录操作The sign-in action in the code-behind in the controller
在 ASP.NET Core 中,对于 Microsoft 标识平台应用程序,“登录”按钮在 Views\Shared\_LoginPartial.cshtml(适用于 MVC 应用)或 Pages\Shared\_LoginPartial.cshtm(适用于 Razor 应用)中公开。In ASP.NET Core, for Microsoft identity platform applications, the Sign in button is exposed in Views\Shared\_LoginPartial.cshtml (for an MVC app) or Pages\Shared\_LoginPartial.cshtm (for a Razor app).仅当用户未经过身份验证时才会显示此按钮。It's displayed only when the user isn't authenticated.即,仅当用户尚未登录或者已注销时才显示。相反,当用户已登录时,将显示“注销”按钮。That is, it's displayed when the user hasn't yet signed in or has signed out. On the contrary, The Sign out button is displayed when the user is already signed-in.请注意,帐户控制器是在“Microsoft.Identity.Web.UI”NuGet 包(位于名为“MicrosoftIdentity”的区域中)中定义的。Note that the Account controller is defined in the Microsoft.Identity.Web.UI NuGet package, in the Area named MicrosoftIdentity
在 ASP.NET MVC 中,注销按钮在 Views\Shared\_LoginPartial.cshtml 中公开。In ASP.NET MVC, the sign-out button is exposed in Views\Shared\_LoginPartial.cshtml.仅当存在已完成身份验证的帐户时,才会显示此按钮。It's displayed only when there's an authenticated account.即,仅当用户事先已登录时才显示。That is, it's displayed when the user has previously signed in.
Python 快速入门中没有登录按钮。In the Python quickstart, there's no sign-in button.进入 Web 应用的根目录时,code-behind 会自动提示用户登录。The code-behind automatically prompts the user for sign-in when it's reaching the root of the web app.请参阅 app.py#L14-L18。See app.py#L14-L18.
@app.route("/")
def index():
if not session.get("user"):
return redirect(url_for("login"))
return render_template('index.html', user=session["user"])
在 ASP.NET 中,在 Web 应用中选择“登录”按钮会触发 AccountController 控制器上的 SignIn 操作。In ASP.NET, selecting the Sign-in button in the web app triggers the SignIn action on the AccountController controller.在以前的 ASP.NET Core 模板版本中,Account 控制器嵌入在 Web 应用中。In previous versions of the ASP.NET core templates, the Account controller was embedded with the web app.现在不再是这样,因为该控制器现在是“Microsoft.Identity.Web.UI”NuGet 包的一部分。That's no longer the case because the controller is now part of the Microsoft.Identity.Web.UI NuGet package.有关详细信息,请参阅 AccountController.cs。See AccountController.cs for details.
此控制器还处理 Azure AD B2C 应用程序。This controller also handles the Azure AD B2C applications.
在 ASP.NET 中,注销是从控制器(例如 AccountController.cs#L16-L23)中的 SignOut() 方法触发的。In ASP.NET, signing out is triggered from the SignOut() method on a controller (for instance, AccountController.cs#L16-L23).此方法不是 ASP.NET 框架的一部分(与 ASP.NET Core 中的情况相反)。This method isn't part of the ASP.NET framework (contrary to what happens in ASP.NET Core).它在提议重定向 URI 后发送 OpenID 登录质询。It sends an OpenID sign-in challenge after proposing a redirect URI.
public void SignIn()
{
// Send an OpenID Connect sign-in request.
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
在 Java 中,注销是通过直接调用 Microsoft 标识平台 logout 终结点并提供 post_logout_redirect_uri 值来处理的。In Java, sign-out is handled by calling the Microsoft identity platform logout endpoint directly and providing the post_logout_redirect_uri value.有关详细信息,请参阅 AuthPageController.java#L30-L48。For details, see AuthPageController.java#L30-L48.
@Controller
public class AuthPageController {
@Autowired
AuthHelper authHelper;
@RequestMapping("/msal4jsample")
public String homepage(){
return "index";
}
@RequestMapping("/msal4jsample/secure/aad")
public ModelAndView securePage(HttpServletRequest httpRequest) throws ParseException {
ModelAndView mav = new ModelAndView("auth_page");
setAccountInfo(mav, httpRequest);
return mav;
}
// More code omitted for simplicity
与其他平台不同,MSAL Python 将负责处理让用户从登录页登录的过程。Unlike other platforms, MSAL Python takes care of letting the user sign in from the login page.请参阅 app.py#L20-L28。See app.py#L20-L28.
@app.route("/login")
def login():
session["state"] = str(uuid.uuid4())
auth_url = _build_msal_app().get_authorization_request_url(
app_config.SCOPE, # Technically we can use an empty list [] to just sign in
# Here we choose to also collect user consent up front
state=session["state"],
redirect_uri=url_for("authorized", _external=True))
return "<a href='%s'>Login with Microsoft Identity</a>" % auth_url
_build_msal_app() 方法在 app.py#L81-L88 中定义,如下所示:The _build_msal_app() method is defined in app.py#L81-L88 as follows:
def _load_cache():
cache = msal.SerializableTokenCache()
if session.get("token_cache"):
cache.deserialize(session["token_cache"])
return cache
def _save_cache(cache):
if cache.has_state_changed:
session["token_cache"] = cache.serialize()
def _build_msal_app(cache=None):
return msal.ConfidentialClientApplication(
app_config.CLIENT_ID, authority=app_config.AUTHORITY,
client_credential=app_config.CLIENT_SECRET, token_cache=cache)
def _get_token_from_cache(scope=None):
cache = _load_cache() # This web app maintains one cache per session
cca = _build_msal_app(cache)
accounts = cca.get_accounts()
if accounts: # So all accounts belong to the current signed-in user
result = cca.acquire_token_silent(scope, account=accounts[0])
_save_cache(cache)
return result
在用户登录到你的应用后,你希望他们能够注销。After the user has signed in to your app, you'll want to enable them to sign out.
注销Sign-out
从 Web 应用注销不仅仅涉及到从 Web 应用的状态中删除有关已登录帐户的信息。Signing out from a web app involves more than removing the information about the signed-in account from the web app's state.该 Web 应用还必须将用户重定向到 Microsoft 标识平台 logout 终结点才能注销。The web app must also redirect the user to the Microsoft identity platform logout endpoint to sign out.
当 Web 应用将用户重定向到 logout 终结点时,此终结点将从浏览器中清除用户的会话。When your web app redirects the user to the logout endpoint, this endpoint clears the user's session from the browser.如果应用尚未进入 logout 终结点,则用户不需要再次输入凭据就能重新通过应用的身份验证。If your app didn't go to the logout endpoint, the user will reauthenticate to your app without entering their credentials again.原因是他们与 Microsoft 标识平台终结点之间建立了有效的单一登录会话。The reason is that they'll have a valid single sign-in session with the Microsoft identity platform endpoint.
在应用程序注册期间,需要注册一个注销后的 URI。During the application registration, you register a post-logout URI.在本教程中,你已在“身份验证”页上“高级设置”部分的“注销 URL”字段中注册了 https://localhost:44321/signout-oidc。 In our tutorial, you registered https://localhost:44321/signout-oidc in the Logout URL field of the Advanced Settings section on the Authentication page.有关详细信息,请参阅注册 webApp 应用。For details, see Register the webApp app.
在应用程序注册期间,需要注册一个注销后的 URI。During the application registration, you register a post-logout URI.在本教程中,你已在“身份验证”页上“高级设置”部分的“注销 URL”字段中注册了 https://localhost:44308/Account/EndSession。 In our tutorial, you registered https://localhost:44308/Account/EndSession in the Logout URL field of the Advanced Settings section on the Authentication page.有关详细信息,请参阅注册 webApp 应用。For details, see Register the webApp app.
在应用程序注册期间,需要注册一个注销后的 URI。During the application registration, you register a post-logout URI.在本教程中,你已在“身份验证”页上“高级设置”部分的“注销 URL”字段中注册了 http://localhost:8080/msal4jsample/sign_out。 In our tutorial, you registered http://localhost:8080/msal4jsample/sign_out in the Logout URL field of the Advanced Settings section on the Authentication page.
在应用程序注册过程中,无需注册额外的注销 URL。During the application registration, you don't need to register an extra logout URL.将在应用的主 URL 上回调应用。The app will be called back on its main URL.
在 ASP.NET 的 Web 应用中选择“注销”按钮会触发 AccountController 控制器上的 SignOut 操作(见下)In ASP.NET, selecting the Sign out button in the web app triggers the SignOut action on the AccountController controller (see below)
在 ASP.NET MVC 中,注销按钮在 Views\Shared\_LoginPartial.cshtml 中公开。In ASP.NET MVC, the sign-out button is exposed in Views\Shared\_LoginPartial.cshtml.仅当存在已完成身份验证的帐户时,才会显示此按钮。It's displayed only when there's an authenticated account.即,仅当用户事先已登录时才显示。That is, it's displayed when the user has previously signed in.
在 Java 快速入门中,注销按钮位于 main/resources/templates/auth_page.html 文件中。In our Java quickstart, the sign-out button is located in the main/resources/templates/auth_page.html file.
在以前的 ASP.NET Core 模板版本中,Account 控制器嵌入在 Web 应用中。In previous versions of the ASP.NET core templates, the Account controller was embedded with the web app.现在不再是这样,因为该控制器现在是“Microsoft.Identity.Web.UI”NuGet 包的一部分。That's no longer the case because the controller is now part of the Microsoft.Identity.Web.UI NuGet package.有关详细信息,请参阅 AccountController.cs。See AccountController.cs for details.
将 OpenID 重定向 URI 设置为 /Account/SignedOut,以便在 Azure AD 完成注销后回调控制器。Sets an OpenID redirect URI to /Account/SignedOut so that the controller is called back when Azure AD has completed the sign-out.
调用 Signout(),让 OpenID Connect 中间件联系 Microsoft 标识平台 logout 终结点。Calls Signout(), which lets the OpenID Connect middleware contact the Microsoft identity platform logout endpoint.然后,终结点将会:The endpoint then:
从浏览器中清除会话 Cookie。Clears the session cookie from the browser.
回调注销 URL。Calls back the logout URL.默认情况下,注销 URL 会显示已注销视图页 SignedOut.cshtml.cs。By default, the logout URL displays the signed-out view page SignedOut.cshtml.cs.此页也作为 MIcrosoft.Identity.Web 的一部分提供。This page is also provided as part of MIcrosoft.Identity.Web.
在 ASP.NET 中,注销是从控制器(例如 AccountController.cs#L25-L31)中的 SignOut() 方法触发的。In ASP.NET, signing out is triggered from the SignOut() method on a controller (for instance, AccountController.cs#L25-L31).与 ASP.NET Core 中的情况相反,此方法不是 ASP.NET 框架的一部分。This method isn't part of the ASP.NET framework, contrary to what happens in ASP.NET Core.该方法:It:
发送 OpenID 注销质询。Sends an OpenID sign-out challenge.
清除缓存。Clears the cache.
重定向到所需的页面。Redirects to the page that it wants.
/// <summary>
/// Send an OpenID Connect sign-out request.
/// </summary>
public void SignOut()
{
HttpContext.GetOwinContext()
.Authentication
.SignOut(CookieAuthenticationDefaults.AuthenticationType);
Response.Redirect("/");
}
在 Java 中,注销是通过直接调用 Microsoft 标识平台 logout 终结点并提供 post_logout_redirect_uri 值来处理的。In Java, sign-out is handled by calling the Microsoft identity platform logout endpoint directly and providing the post_logout_redirect_uri value.有关详细信息,请参阅 AuthPageController.java#L50-L60。For details, see AuthPageController.java#L50-L60.
@app.route("/logout")
def logout():
session.clear() # Wipe out the user and the token cache from the session
return redirect( # Also need to log out from the Microsoft Identity platform
"https://login.partner.microsoftonline.cn/common/oauth2/v2.0/logout"
"?post_logout_redirect_uri=" + url_for("index", _external=True))
截获对 logout 终结点的调用Intercepting the call to the logout endpoint
注销后的 URI 使应用程序能够参与全局注销。The post-logout URI enables applications to participate in the global sign-out.
ASP.NET Core OpenID Connect 中间件提供名为 OnRedirectToIdentityProviderForSignOut 的 OpenID Connect 事件,可让应用截获对 Microsoft 标识平台 logout 终结点的调用。The ASP.NET Core OpenID Connect middleware enables your app to intercept the call to the Microsoft identity platform logout endpoint by providing an OpenID Connect event named OnRedirectToIdentityProviderForSignOut.这由 Microsoft.Identity.Web 自动处理(在 Web 应用调用 Web API 的情况下会清除帐户)This is handled automatically by Microsoft.Identity.Web (which clears accounts in the case where your web app calls web apis)
在 ASP.NET 中,需委托中间件执行注销,并清除会话 Cookie:In ASP.NET, you delegate to the middleware to execute the sign-out, clearing the session cookie:
public class AccountController : Controller
{
...
public void EndSession()
{
Request.GetOwinContext().Authentication.SignOut();
Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
this.HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
}
}
在 Java 快速入门中,注销后的重定向 URI 只显示 index.html 页。In the Java quickstart, the post-logout redirect URI just displays the index.html page.
在 Python 快速入门中,注销后的重定向 URI 只显示 index.html 页。In the Python quickstart, the post-logout redirect URI just displays the index.html page.
协议Protocol
若要了解有关注销的详细信息,请阅读 OpenID Connect 提供的协议文档。If you want to learn more about sign-out, read the protocol documentation that's available from Open ID Connect.