mirror of
https://github.com/OpenBankProject/OBP-Hydra-Identity-Provider.git
synced 2026-02-06 02:37:34 +00:00
feature/Add Redis Log Widget
This commit is contained in:
parent
f7406bbdee
commit
6768c38f85
4
pom.xml
4
pom.xml
@ -71,6 +71,10 @@
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>1.62</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
20
src/main/java/com/openbankproject/RedisConfig.java
Normal file
20
src/main/java/com/openbankproject/RedisConfig.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.openbankproject;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(new StringRedisSerializer());
|
||||
return template;
|
||||
}
|
||||
}
|
||||
47
src/main/java/com/openbankproject/RedisService.java
Normal file
47
src/main/java/com/openbankproject/RedisService.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.openbankproject;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class RedisService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
public void save(String key, String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
// Save a value with a TTL (Time-to-Live)
|
||||
public void saveWithTTL(String key, String value, long timeoutInSeconds) {
|
||||
save(key, value);
|
||||
// Set TTL for the key
|
||||
redisTemplate.expire(key, timeoutInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// Save a value with a TTL (Time-to-Live)
|
||||
public void appendWithTTL(String key, String value, long timeoutInSeconds) {
|
||||
String currentValue = get(key);
|
||||
String currentValuePrintFriendly = currentValue != null ? currentValue : "";
|
||||
save(key, currentValuePrintFriendly + value);
|
||||
// Set TTL for the key
|
||||
redisTemplate.expire(key, timeoutInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
public String get(String key) {
|
||||
return (String) redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
public void readLogFromRedis(HttpSession session, Model model) {
|
||||
String key = "log-entry-for-session-id: " + session.getId();
|
||||
String logEntries = get(key);
|
||||
model.addAttribute("logEntriesForHtml", logEntries);
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@ -33,6 +34,7 @@ import java.util.function.Function;
|
||||
import static com.openbankproject.oauth2.util.ControllerUtils.buildDirectLoginHeader;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = "com.openbankproject") // Ensure this package is scanned
|
||||
public class Oauth2Application {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Oauth2Application.class);
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.nimbusds.jose.JWSObject;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import com.openbankproject.JwsUtil;
|
||||
import com.openbankproject.RedisService;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -17,6 +18,7 @@ import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -41,6 +43,7 @@ import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -120,24 +123,78 @@ public class RestTemplateConfig {
|
||||
|
||||
private String getSessionId() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attributes != null) {
|
||||
if (attributes != null && attributes.getRequest() != null && attributes.getRequest().getSession(false) != null ) {
|
||||
return attributes.getRequest().getSession(false).getId(); // Get the existing session, don't create a new one
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
public String printUtcDateTime() {
|
||||
Instant now = Instant.now();
|
||||
return "at UTC Time: " + now.toString();
|
||||
}
|
||||
|
||||
private StringBuilder saveRequestInfoToRedis(HttpRequest request, String body) {
|
||||
System.out.println("Saving to Redis...");
|
||||
StringBuilder logEntry = buildRequestInfo(request, body);
|
||||
String key = "log-entry-for-session-id: " + getSessionId();
|
||||
String value = logEntry.toString();
|
||||
redisService.appendWithTTL(key, value, 300);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
private StringBuilder buildRequestInfo(HttpRequest request, String body) {
|
||||
StringBuilder logEntry = new StringBuilder();
|
||||
logEntry.append("============= Request begin " + printUtcDateTime() + " =============\n")
|
||||
.append("=== Session ID: ").append(getSessionId()).append("\n")
|
||||
.append("=== Status Line : ").append(request.getRequestLine()).append("\n")
|
||||
.append("=== Headers : ").append(StringUtils.join(request.getAllHeaders(), "; ")).append("\n")
|
||||
.append("=== Request body: ").append(body).append("\n")
|
||||
.append("============= Request end " + printUtcDateTime() + " =============\n");
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
private StringBuilder saveResponseInfoTRedis(HttpResponse response, String body) {
|
||||
System.out.println("Saving to Redis...");
|
||||
StringBuilder logEntry = buildResponseInfo(response, body);
|
||||
String key = "log-entry-for-session-id: " + getSessionId();
|
||||
String value = logEntry.toString();
|
||||
redisService.appendWithTTL(key, value, 300);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
private StringBuilder buildResponseInfo(HttpResponse response, String body) {
|
||||
StringBuilder logEntry = new StringBuilder();
|
||||
logEntry.append("============= Response begin " + printUtcDateTime() + " =============\n")
|
||||
.append("=== Session ID: ").append(getSessionId()).append("\n")
|
||||
.append("=== Status Line : ").append(response.getStatusLine()).append("\n")
|
||||
.append("=== Headers : ").append(StringUtils.join(response.getAllHeaders(), "; ")).append("\n")
|
||||
.append("=== Response body: ").append(body).append("\n")
|
||||
.append("============= Response end " + printUtcDateTime() + " =============\n");
|
||||
return logEntry;
|
||||
}
|
||||
private void traceRequest(HttpRequest request, String body) throws IOException {
|
||||
// Standard output
|
||||
logger.info("=========================== request begin ================================================ Session ID : {}", getSessionId());
|
||||
logger.info("=== Request Line : {}, Session ID : {}", request.getRequestLine(), getSessionId());
|
||||
logger.info("=== Headers : {}, Session ID : {}", StringUtils.join(request.getAllHeaders(), "; "), getSessionId());
|
||||
logger.info("=== Request body: {}, Session ID : {}", body, getSessionId());
|
||||
logger.info("============================= request end ================================================ Session ID : {}", getSessionId());
|
||||
// Save to Redis
|
||||
saveRequestInfoToRedis(request, body).toString();
|
||||
}
|
||||
private void traceResponse(HttpResponse response, String body) throws IOException {
|
||||
// Standard output
|
||||
logger.info("=========================== response begin ================================================ Session ID : {}", getSessionId());
|
||||
logger.info("=== Status Line : {}, Session ID : {}", response.getStatusLine(), getSessionId());
|
||||
logger.info("=== Headers : {}, Session ID : {}", StringUtils.join(response.getAllHeaders(), "; "), getSessionId());
|
||||
logger.info("=== Response body: {}, Session ID : {}", body, getSessionId());
|
||||
logger.info("=========================== response end =================================================== Session ID : {}", getSessionId());
|
||||
// Save to Redis
|
||||
saveResponseInfoTRedis(response, body);
|
||||
}
|
||||
private void responseIntercept(org.apache.http.HttpResponse response, HttpContext httpContext) throws IOException {
|
||||
HttpRequest req = (HttpRequest)httpContext.getAttribute("http.request");
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.openbankproject.oauth2.controller;
|
||||
|
||||
import com.nimbusds.jose.util.X509CertUtils;
|
||||
import com.openbankproject.RedisService;
|
||||
import com.openbankproject.oauth2.model.AccessToViewRequest;
|
||||
import com.openbankproject.oauth2.model.AccountMini;
|
||||
import com.openbankproject.oauth2.model.Accounts;
|
||||
@ -9,6 +10,7 @@ import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@ -95,6 +97,9 @@ public class ConsentController {
|
||||
|
||||
private String idTokenSignHashAlg;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@PostConstruct
|
||||
private void initiate() {
|
||||
final Map<String, List<Map<String, String>>> keySet = restTemplate.getForObject(keySetUrl, Map.class);
|
||||
@ -228,7 +233,8 @@ public class ConsentController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
redisService.readLogFromRedis(session, model);
|
||||
model.addAttribute("consents", consents);
|
||||
model.addAttribute("showBankLogo", showBankLogo);
|
||||
model.addAttribute("obpBaseUrl", obpBaseUrl);
|
||||
@ -280,6 +286,9 @@ public class ConsentController {
|
||||
ResponseEntity<Map> response2 = restTemplate.exchange(url, method, entity2, Map.class);
|
||||
String redirect = (String) session.getAttribute("acceptConsentResponse.getRedirectTo()");
|
||||
logger.info("redirect:" + redirect);
|
||||
|
||||
redisService.readLogFromRedis(session, model);
|
||||
|
||||
return "redirect:" + redirect;
|
||||
} catch (Exception e) {
|
||||
String error = "Sorry! The one time password (OTP) you supplied is incorrect.";
|
||||
@ -294,8 +303,8 @@ public class ConsentController {
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping(value="/revoke_consents", params = "consent_challenge")
|
||||
public String revokeConsents(@RequestParam String consent_challenge,
|
||||
@RequestParam(value="consents", required = false) String[] consentIds,
|
||||
@ -325,6 +334,7 @@ public class ConsentController {
|
||||
return "error";
|
||||
}
|
||||
model.addAttribute("errorMsg", "All selected consents have been deleted!");
|
||||
redisService.readLogFromRedis(session, model);
|
||||
return "error";
|
||||
}
|
||||
|
||||
@ -489,7 +499,9 @@ public class ConsentController {
|
||||
ResponseEntity<Map> authorizationIds = restTemplate.exchange(getConsentAuthorisation.replace("CONSENT_ID", consentId), HttpMethod.GET, entity, Map.class);
|
||||
ArrayList<String> list = (ArrayList<String>)authorizationIds.getBody().get("authorisationIds");
|
||||
model.addAttribute("authorization_ids", String.join(", ", list));
|
||||
|
||||
|
||||
redisService.readLogFromRedis(session, model);
|
||||
|
||||
model.addAttribute("consent_challenge", consent_challenge);
|
||||
session.setAttribute("acceptConsentResponse.getRedirectTo()", acceptConsentResponse.getRedirectTo());
|
||||
logger.info("acceptConsentResponse.getRedirectTo():" + acceptConsentResponse.getRedirectTo());
|
||||
@ -498,8 +510,13 @@ public class ConsentController {
|
||||
model.addAttribute("consent_challenge", consent_challenge);
|
||||
session.setAttribute("acceptConsentResponse.getRedirectTo()", acceptConsentResponse.getRedirectTo());
|
||||
logger.info("acceptConsentResponse.getRedirectTo():" + acceptConsentResponse.getRedirectTo());
|
||||
|
||||
redisService.readLogFromRedis(session, model);
|
||||
|
||||
return "sca_modal";
|
||||
} else {
|
||||
redisService.readLogFromRedis(session, model);
|
||||
|
||||
return "redirect:" + acceptConsentResponse.getRedirectTo();
|
||||
}
|
||||
} catch (Exception unhandledException) {
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package com.openbankproject.oauth2.controller;
|
||||
|
||||
import com.openbankproject.RedisService;
|
||||
import com.openbankproject.oauth2.model.DirectLoginResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@ -68,6 +70,9 @@ public class LoginController implements ServletContextAware {
|
||||
private String showBankLogo;
|
||||
@Value("${logo.bank.url:#}")
|
||||
private String bankLogoUrl;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
/**
|
||||
* initiate global variable
|
||||
@ -179,8 +184,10 @@ public class LoginController implements ServletContextAware {
|
||||
AcceptLoginRequest acceptLoginRequest = new AcceptLoginRequest();
|
||||
acceptLoginRequest.setSubject(loginRequest.getSubject());
|
||||
CompletedRequest response = hydraAdmin.acceptLoginRequest(login_challenge, acceptLoginRequest);
|
||||
redisService.readLogFromRedis(session, model);
|
||||
return "redirect:" + response.getRedirectTo();
|
||||
} else {
|
||||
redisService.readLogFromRedis(session, model);
|
||||
return "login";
|
||||
}
|
||||
} catch (ApiException e) {
|
||||
|
||||
@ -105,6 +105,8 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -51,6 +51,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
<span id="warning_msg" th:utext="${errorMsg}">He show some error message.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
15
src/main/resources/templates/redis-log-widget.html
Normal file
15
src/main/resources/templates/redis-log-widget.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!-- redis-log-widget.html -->
|
||||
<div th:fragment="redisLogWidget">
|
||||
<hr>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-info" type="button" data-toggle="collapse" data-target="#logEntriesContent" aria-expanded="false" aria-controls="logEntriesContent">
|
||||
Show/Hide log of Hydra Identity Provider app
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse mt-3" id="logEntriesContent">
|
||||
<div class="alert alert-info alert-dismissible col-md-12" role="alert" th:if="${logEntriesForHtml}">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<span id="log_entries_msg" th:utext="${logEntriesForHtml}" style="white-space: pre-wrap;">Not implemented</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -64,6 +64,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:insert="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user