1. 簡介
默認情況下,JHipster 應用程序使用本地數據存儲來存儲用户名和密碼。然而,在許多實際場景中,可能需要使用現有外部服務進行身份驗證。
在本教程中,我們將學習如何在 JHipster 中使用外部服務進行身份驗證。這可以是一個流行的服務,例如 LDAP、社交登錄,或者任何接受用户名和密碼的自定義服務。
2. JHipster 中的身份驗證
JHipster 使用 Spring Security 進行身份驗證。<em >AuthenticationManager</em> 類負責驗證用户名和密碼。
默認的 <em >AuthenticationManager</em> 在 JHipster 中僅檢查用户名和密碼與本地數據存儲中的匹配情況。該本地數據存儲可以是 MySQL、PostgreSQL、MongoDB 或 JHipster 支持的任何其他替代方案。
需要注意的是,<em >AuthenticationManager</em> 僅用於初始登錄。一旦用户已通過身份驗證,他們將收到 JSON Web Token (JWT),該 JWT 用於後續的 API 調用。
2.1. 在 JHipster 中更改身份驗證
如果我們的數據存儲中已經包含用户名和密碼,或者某個服務正在為我們執行身份驗證,該怎麼辦?
為了提供自定義身份驗證方案,我們只需創建一個新的類型為 <em >AuthenticationManager</em> 的 Bean。 這將覆蓋默認實現。
下面是一個示例,展示瞭如何創建自定義 <em >AuthenticationManager</em>。 它僅有一個方法需要實現:
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);
}
}
}在此示例中,我們從 身份驗證 對象中傳遞用户名和憑據到外部 API。
如果調用成功,我們將返回一個新的 UsernamePasswordAuthenticationToken 以指示成功。請注意,我們還會創建一個本地用户條目,稍後將討論它。
如果調用失敗,我們將拋出 某種類型的 AuthenticationException,以便 Spring Security 可以優雅地為我們回退。
此示例旨在簡單明瞭,以展示自定義身份驗證的基本原理。但是,它還可以執行更復雜的操作,例如 LDAP 綁定和身份驗證或 使用 OAuth。
3. 其他注意事項
此前,我們主要關注了 JHipster 中的身份驗證流程。但 JHipster 應用的其他一些區域也需要進行修改。
3.1 前端代碼
JHipster 的默認代碼實現了以下用户註冊和激活流程:
- 用户使用他們的電子郵件和其他所需詳細信息註冊帳户。
- JHipster 創建帳户並將其設置為不活動狀態,然後向新用户發送包含激活鏈接的電子郵件。
- 用户點擊鏈接後,帳户將被標記為活動狀態。
對於密碼重置也有類似流程。
這些流程在 JHipster 管理用户帳户時都適用。但是,當我們依賴外部服務進行身份驗證時,就不需要這些流程。
因此,我們需要採取措施確保這些帳户管理功能對用户不可用。
這意味着,根據 JHipster 應用程序中使用的框架(例如 Angular 或 React),從 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 API
在大多數情況下,只需刪除前端賬户管理代碼即可。但是,為了確保賬户管理代碼不會被調用,我們還可以鎖定相關的 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. 郵件模板
JHipster 應用程序自帶一套默認的郵件模板,用於賬户註冊、激活和密碼重置。 前幾步操作有效地阻止了默認郵件的發送,但在某些情況下,我們可能希望重用它們。
例如,當用户首次登錄時,我們可能希望發送歡迎郵件。 默認模板包含賬户激活步驟,因此我們需要對其進行修改。
所有郵件模板都位於 resources/templates/mail 目錄下。 它們是使用 Thymeleaf 將 Java 代碼中的數據傳遞到郵件中的 HTML 文件。
我們只需要編輯模板以包含所需文本和佈局,然後使用 MailService 發送它。
3.4. 角色
當我們創建本地 JHipster 用户條目時,必須確保它至少擁有一個角色。通常,默認的 USER 角色對新賬户來説已經足夠。
如果外部服務提供自己的角色映射,則需要執行以下兩個步驟:
- 確保 JHipster 中存在任何自定義角色
- 更新我們的自定義 AuthenticationManager 以在創建新用户時設置自定義角色
JHipster 還提供了一個管理界面,用於向用户添加和刪除角色。
3.5. 賬户移除
JHipster 還提供賬户移除管理視圖和 API。 此視圖僅對管理員用户可用。
我們可以像賬户註冊和密碼重置那樣移除和限制此代碼,但實際上並不必要。 我們的自定義 AuthenticationManager 會在有人登錄時始終創建一個新的賬户條目,因此刪除賬户實際上並不能做太多。
4. 結論
在本教程中,我們學習瞭如何用自定義認證方案替換默認的 JHipster 認證代碼。這可能包括 LDAP、OIDC 或任何接受用户名和密碼的服務。
我們還了解到使用外部認證服務也需要對 JHipster 應用程序的其他部分進行一些修改,包括前端視圖、API 等。