1. 簡介
默認情況下,JHipster 應用程序使用本地數據存儲來存儲用户名和密碼。然而,在許多實際場景中,可能需要使用現有外部服務進行身份驗證。
在本教程中,我們將探討如何在 JHipster 中使用外部服務進行身份驗證。這可以是一個著名的服務,例如 LDAP、社交登錄,或任何接受用户名和密碼的任意服務。
2. 身份驗證在 JHipster 中的使用
JHipster 使用 Spring Security 進行身份驗證。 AuthenticationManager 類負責驗證用户名和密碼。
JHipster 的默認 AuthenticationManager 類 僅檢查用户名和密碼與本地數據存儲。 這可能包括 MySQL、PostgreSQL、MongoDB 或 JHipster 支持的任何替代方案。
重要的是要注意,AuthenticationManager 類僅用於初始登錄。 一旦用户已進行身份驗證,他們將收到 JSON Web Token (JWT),該令牌用於後續的 API 調用。
2.1. 修改 JHipster 中的身份驗證
但是,如果我們在數據存儲中已經包含用户名和密碼,或者一個服務正在為我們執行身份驗證,該怎麼辦?
為了提供自定義身份驗證方案,我們只需創建一個新的 AuthenticationManager 類型的 Bean。 這將優先於默認實現。
以下是一個示例,展示瞭如何創建自定義 AuthenticationManager。 它僅有一個方法需要實現:
public class CustomAuthenticationManager implements AuthenticationManager {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
ResponseEntity<LoginResponse> response =
restTemplate.postForEntity(REMOTE_LOGIN_URL, loginRequest, LoginResponse.class);
if(response.getStatusCode().is2xxSuccessful()) {
String login = authentication.getPrincipal().toString();
User user = userService.getUserWithAuthoritiesByLogin(login)
.orElseGet(() -> userService.createUser(
createUserDTO(response.getBody(), authentication)));
return createAuthentication(authentication, user);
}
else {
throw new BadCredentialsException("Invalid username or password");
}
}
catch (Exception e) {
throw new AuthenticationServiceException("Failed to login", e);
}
}
}
在這個示例中,我們將用户名和憑據從 Authentication 對象傳遞到外部 API。
如果調用成功,我們將返回一個新的 UsernamePasswordAuthenticationToken 對象,以指示成功。 請注意,我們還將創建一個本地用户條目,稍後將討論它。
如果調用失敗,我們將拋出某種 AuthenticationException 變體,以便 Spring Security 可以為我們優雅地回退。
這個示例是故意簡單的,旨在展示基本內容。 但是,它可以執行更復雜的操作,例如 LDAP 綁定和身份驗證或 使用 OAuth。
3. Other Considerations
截至目前,我們已經專注於 JHipster 中的身份驗證流程。但還有幾個其他需要我們修改的 JHipster 應用程序領域。
3.1. Front-End Code
默認的 JHipster 代碼實現了以下用户註冊和激活流程:
- 用户使用他們的電子郵件和其他所需詳細信息註冊帳户
- JHipster 創建帳户並將其設置為停用狀態,然後將電子郵件發送給新用户,其中包含激活鏈接
- 點擊鏈接後,用户的帳户將被標記為已激活
對於密碼重置也有類似流程。
這些在 JHipster 管理用户帳户時都適用。但當我們在外部服務上進行身份驗證時,它們就不必要了。
因此,我們需要採取措施,確保這些帳户管理功能對用户不可訪問。
這意味着從 Angular 或 React 代碼中刪除它們,具體取決於 JHipster 應用程序中使用的框架。
例如,使用 Angular 作為登錄提示,默認包含指向密碼重置和註冊的鏈接。我們應該從 app/shared/login/login.component.html 中刪除它們:
<div class="alert alert-warning">
<a class="alert-link" (click)="requestResetPassword()">Did you forget your password?</a>
</div>
<div class="alert alert-warning">
<span>You don't have an account yet?</span>
<a class="alert-link" (click)="register()">Register a new account</a>
</div>
我們還需要從 app/layouts/navbar/navbar.component.html 中刪除不需要的導航菜單項:
<li *ngSwitchCase="true">
<a class="dropdown-item" routerLink="password" routerLinkActive="active" (click)="collapseNavbar()">
<fa-icon icon="clock" fixedWidth="true"></fa-icon>
<span>Password</span>
</a>
</li>
和
<li *ngSwitchCase="false">
<a class="dropdown-item" routerLink="register" routerLinkActive="active" (click)="collapseNavbar()">
<fa-icon icon="user-plus" fixedWidth="true"></fa-icon>
<span>Register</span>
</a>
</li>
即使我們刪除了所有鏈接,用户仍然可以手動導航到這些頁面。最終步驟是從 app/account/account.route.ts 中刪除未使用的 Angular 路由。
完成這些操作後,僅設置“設置”路由保留:
import { settingsRoute } from './';
const ACCOUNT_ROUTES = [settingsRoute];
3.2. Java APIs
在大多數情況下,僅僅刪除前端帳户管理代碼就足夠了。但是,為了絕對確定帳户管理代碼未被調用,我們還可以鎖定相關的 Java API。
最快的方法是更新 SecurityConfiguration 類以拒絕指向相關 URL 的所有請求:
.antMatchers("/api/register").denyAll()
.antMatchers("/api/activate").denyAll()
.antMatchers("/api/account/reset-password/init").denyAll()
.antMatchers("/api/account/reset-password/finish").denyAll()
這將阻止任何遠程訪問 API,而無需刪除任何代碼。
3.3. Email Templates
JHipster 應用程序附帶一組默認電子郵件模板,用於帳户註冊、激活和密碼重置。 之前的步驟有效地阻止了默認電子郵件的發送,但在某些情況下,我們可能想重用它們。
例如,當用户首次登錄時,我們可能想發送歡迎電子郵件。默認模板包含帳户激活步驟,因此我們需要對其進行修改。
所有電子郵件模板位於 resources/templates/mail 中。它們是使用 Thymeleaf 將 Java 代碼中的數據傳遞到電子郵件中的 HTML 文件。
我們只需要編輯模板以包含所需的文本和佈局,然後使用 MailService 發送它。
3.4. Roles
當我們創建本地 JHipster 用户條目時,我們也需要確保它至少具有一個角色。通常,默認 USER 角色對新帳户來説就足夠了。
如果外部服務提供自己的角色映射,我們有兩步:
- 確保在 JHipster 中存在任何自定義角色
- 更新我們的自定義 AuthenticationManager 以在創建新用户時設置自定義角色
JHipster 還提供了一個用於添加和刪除角色到用户管理界面。
3.5. Account Removal
值得一提的是,JHipster 還提供帳户刪除管理視圖和 API。此視圖僅對管理員用户可用。
我們可以刪除並限制此代碼,就像我們為註冊和密碼重置所做的那樣。我們的自定義 AuthenticationManager 始終會在有人登錄時創建新的帳户條目,因此刪除帳户實際上並沒有做太多。
4. 結論
在本教程中,我們學習瞭如何用自定義認證方案替換默認的 JHipster 認證代碼。這可以包括 LDAP、OIDC 或任何接受用户名和密碼的服務。
我們也瞭解到,使用外部認證服務還需要對 JHipster 應用程序的其他部分進行修改。這包括前端視圖、API 以及更多內容。