AEM 6.2中基于Token的外部用户认证实现方案咨询
Step-by-Step Implementation for JWT Authentication in AEM
I’ve implemented similar flows in AEM before—here’s a practical breakdown of how to build this:
1. Create an OSGi Servlet to Handle Authentication Requests
This servlet will accept the form submission, process credentials, call your legacy API, and manage the JWT token.
Servlet Code Example
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.json.JSONObject; import javax.servlet.Servlet; import javax.servlet.ServletException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; @Component( service = Servlet.class, property = { "sling.servlet.paths=/bin/legacy-auth/login", "sling.servlet.methods=POST", "sling.servlet.extensions=json" } ) public class LegacyAuthServlet extends SlingAllMethodsServlet { private static final Logger LOG = LoggerFactory.getLogger(LegacyAuthServlet.class); private static final String LEGACY_API_AUTH_URL = "https://your-legacy-api-domain.com/auth/token"; // Replace with your API URL @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { // 1. Grab form credentials String username = request.getParameter("username"); String password = request.getParameter("password"); if (username == null || password == null || username.isBlank() || password.isBlank()) { response.setStatus(SlingHttpServletResponse.SC_BAD_REQUEST); response.getWriter().write("{\"error\": \"Username or password cannot be empty\"}"); return; } try { // 2. Encode credentials (adjust based on your API's requirements) // Example: Basic Auth encoding String rawCreds = username + ":" + password; String encodedCreds = Base64.getEncoder().encodeToString(rawCreds.getBytes(StandardCharsets.UTF_8)); // 3. Call legacy authentication API HttpClient httpClient = HttpClients.createDefault(); HttpPost authPost = new HttpPost(LEGACY_API_AUTH_URL); // Set headers per your API specs authPost.setHeader("Authorization", "Basic " + encodedCreds); authPost.setHeader("Content-Type", "application/json"); // If your API expects a JSON payload instead of Basic Auth: // JSONObject payload = new JSONObject(); // payload.put("username", username); // payload.put("password", password); // authPost.setEntity(new StringEntity(payload.toString())); HttpResponse apiResponse = httpClient.execute(authPost); int statusCode = apiResponse.getStatusLine().getStatusCode(); if (statusCode == SlingHttpServletResponse.SC_OK) { // 4. Extract JWT from API response HttpEntity responseEntity = apiResponse.getEntity(); String responseBody = EntityUtils.toString(responseEntity); JSONObject jsonResponse = new JSONObject(responseBody); String jwtToken = jsonResponse.getString("token"); // Adjust field name to match your API // 5. Store JWT securely in an HttpOnly cookie setSecureAuthCookie(response, jwtToken); // Return success response to frontend response.setStatus(SlingHttpServletResponse.SC_OK); response.getWriter().write("{\"success\": true, \"message\": \"Login successful\"}"); } else { // Handle failed authentication response.setStatus(statusCode); response.getWriter().write("{\"error\": \"Invalid credentials or API error\"}"); } } catch (Exception e) { LOG.error("Authentication failed due to internal error", e); response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("{\"error\": \"Server encountered an issue during login\"}"); } } private void setSecureAuthCookie(SlingHttpServletResponse response, String jwtToken) { javax.servlet.http.Cookie authCookie = new javax.servlet.http.Cookie("legacy_auth_token", jwtToken); authCookie.setHttpOnly(true); // Block JS access to prevent XSS authCookie.setSecure(true); // Only send over HTTPS authCookie.setSameSite(javax.servlet.http.Cookie.SameSite.STRICT); // Mitigate CSRF authCookie.setPath("/"); // Make cookie available across the entire site authCookie.setMaxAge(86400); // Expire after 1 day (adjust as needed) response.addCookie(authCookie); } }
2. Project Dependencies
Add these to your pom.xml to enable HTTP calls and JSON parsing:
<!-- Apache HttpClient for API calls --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> <scope>provided</scope> </dependency> <!-- JSON parsing library --> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20230227</version> <scope>provided</scope> </dependency>
3. Frontend Form Integration
Your public site’s login form should submit to the servlet path:
<form action="/bin/legacy-auth/login.json" method="POST"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username" required> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password" required> </div> <button type="submit">Login</button> </form>
4. Key Security Practices
- Avoid Hardcoding: Move the legacy API URL to an OSGi configuration so you can update it without redeploying code.
- Input Sanitization: Sanitize username/password inputs to prevent injection attacks.
- Rate Limiting: Add rate limiting to the servlet (via AEM Dispatcher or custom code) to block brute-force attempts.
- Token Validation: For protected resources, create a filter that checks the JWT cookie, validates the token (either via the legacy API or signature verification), and allows/blocks access.
内容的提问来源于stack exchange,提问作者isystems_uk
相关产品推荐
相关产品推荐

