Merge branch 'hotfix/1.9.4'
This commit is contained in:
commit
8530edcaea
19 changed files with 202 additions and 137 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||||
<artifactId>fl</artifactId>
|
<artifactId>fl</artifactId>
|
||||||
<version>1.9.3-SNAPSHOT</version>
|
<version>1.9.4-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||||
<artifactId>backend</artifactId>
|
<artifactId>backend</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,11 @@
|
||||||
package ru.micord.ervu.controller;
|
package ru.micord.ervu.controller;
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.apache.kafka.common.utils.Bytes;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import ru.micord.ervu.converter.SummonsResponseDataConverter;
|
|
||||||
import ru.micord.ervu.dto.SubpoenaRequestDto;
|
|
||||||
import ru.micord.ervu.dto.SubpoenaResponseDto;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import proto.ervu.rp.summons.SummonsResponseData;
|
import ru.micord.ervu.dto.SubpoenaResponseDto;
|
||||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
import ru.micord.ervu.service.SubpoenaService;
|
||||||
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author gulnaz
|
* @author gulnaz
|
||||||
|
|
@ -20,41 +13,15 @@ import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
||||||
@RestController
|
@RestController
|
||||||
public class ErvuDataController {
|
public class ErvuDataController {
|
||||||
|
|
||||||
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
|
private final SubpoenaService subpoenaService;
|
||||||
private final SummonsResponseDataConverter converter;
|
|
||||||
|
|
||||||
@Value("${ervu.kafka.recruit.request.topic}")
|
@Autowired
|
||||||
private String recruitRequestTopic;
|
public ErvuDataController(SubpoenaService subpoenaService) {
|
||||||
@Value("${ervu.kafka.recruit.reply.topic}")
|
this.subpoenaService = subpoenaService;
|
||||||
private String recruitReplyTopic;
|
|
||||||
|
|
||||||
public ErvuDataController(
|
|
||||||
@Qualifier("recruit") ReplyingKafkaService<Object, Bytes> replyingKafkaService,
|
|
||||||
SummonsResponseDataConverter converter) {
|
|
||||||
this.replyingKafkaService = replyingKafkaService;
|
|
||||||
this.converter = converter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(
|
@GetMapping(value = "/recruit", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
value = "/recruit",
|
|
||||||
produces = MediaType.APPLICATION_JSON_VALUE
|
|
||||||
)
|
|
||||||
public SubpoenaResponseDto getData() {
|
public SubpoenaResponseDto getData() {
|
||||||
String ervuId = SecurityUtil.getErvuId();
|
return subpoenaService.getSubpoenaData();
|
||||||
|
|
||||||
if (ervuId == null) {
|
|
||||||
return new SubpoenaResponseDto.Builder().build();
|
|
||||||
}
|
|
||||||
SubpoenaRequestDto subpoenaRequestDto = new SubpoenaRequestDto(ervuId);
|
|
||||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(recruitRequestTopic,
|
|
||||||
recruitReplyTopic, subpoenaRequestDto).get();
|
|
||||||
|
|
||||||
try {
|
|
||||||
SummonsResponseData responseData = SummonsResponseData.parseFrom(reply);
|
|
||||||
return converter.convert(responseData);
|
|
||||||
}
|
|
||||||
catch (InvalidProtocolBufferException e) {
|
|
||||||
throw new RuntimeException("Failed to parse data", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ public class LogoutSuccessHandler
|
||||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||||
Authentication authentication) throws IOException {
|
Authentication authentication) throws IOException {
|
||||||
String url = esiaAuthService.logout(request, response);
|
String url = esiaAuthService.logout(request, response);
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
response.sendRedirect(url);
|
||||||
response.getWriter().write(url);
|
|
||||||
response.getWriter().flush();
|
|
||||||
CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request);
|
CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request);
|
||||||
this.csrfTokenRepository.saveToken(csrfToken, request, response);
|
this.csrfTokenRepository.saveToken(csrfToken, request, response);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ public class EsiaConfig {
|
||||||
@Value("${esia.redirect.url}")
|
@Value("${esia.redirect.url}")
|
||||||
private String redirectUrl;
|
private String redirectUrl;
|
||||||
|
|
||||||
|
@Value("${esia.logout.redirect.url}")
|
||||||
|
private String logoutRedirectUrl;
|
||||||
|
|
||||||
@Value("${sign.url}")
|
@Value("${sign.url}")
|
||||||
private String signUrl;
|
private String signUrl;
|
||||||
|
|
||||||
|
|
@ -86,4 +89,8 @@ public class EsiaConfig {
|
||||||
public String getEsiaTokenUrl() {
|
public String getEsiaTokenUrl() {
|
||||||
return esiaTokenUrl;
|
return esiaTokenUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLogoutRedirectUrl() {
|
||||||
|
return logoutRedirectUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
|
@ -111,7 +110,7 @@ public class EsiaAuthService {
|
||||||
"redirect_uri", redirectUrlEncoded,
|
"redirect_uri", redirectUrlEncoded,
|
||||||
"client_certificate_hash", esiaConfig.getClientCertHash());
|
"client_certificate_hash", esiaConfig.getClientCertHash());
|
||||||
|
|
||||||
return makeRequest(url, params);
|
return buildUrl(url, params);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
@ -134,12 +133,13 @@ public class EsiaAuthService {
|
||||||
.replace("+", "%20");
|
.replace("+", "%20");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String makeRequest(URL url, Map<String, String> params) {
|
private static String buildUrl(URL url, Map<String, String> params) {
|
||||||
StringBuilder uriBuilder = new StringBuilder(url.toString());
|
StringBuilder uriBuilder = new StringBuilder(url.toString());
|
||||||
uriBuilder.append('?');
|
uriBuilder.append('?');
|
||||||
for (Map.Entry<String, String> node : params.entrySet()) {
|
for (Map.Entry<String, String> node : params.entrySet()) {
|
||||||
uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&");
|
uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&");
|
||||||
}
|
}
|
||||||
|
uriBuilder.deleteCharAt(uriBuilder.length() - 1);
|
||||||
return uriBuilder.toString();
|
return uriBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,8 +204,7 @@ public class EsiaAuthService {
|
||||||
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
|
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
|
||||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
||||||
int expiry = tokenResponse.getExpires_in().intValue();
|
int expiry = tokenResponse.getExpires_in().intValue();
|
||||||
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
|
securityHelper.addAccessCookies(response, token.getValue(), expiry);
|
||||||
response.addCookie(accessCookie);
|
|
||||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||||
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
|
|
@ -214,8 +213,6 @@ public class EsiaAuthService {
|
||||||
authenticationManager.authenticate(jwtAuthentication);
|
authenticationManager.authenticate(jwtAuthentication);
|
||||||
context.setAuthentication(jwtAuthentication);
|
context.setAuthentication(jwtAuthentication);
|
||||||
SecurityContextHolder.setContext(context);
|
SecurityContextHolder.setContext(context);
|
||||||
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
|
|
||||||
response.addCookie(authMarkerCookie);
|
|
||||||
return ResponseEntity.ok("Authentication successful");
|
return ResponseEntity.ok("Authentication successful");
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|
@ -281,8 +278,7 @@ public class EsiaAuthService {
|
||||||
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
|
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
|
||||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
||||||
int expiry = tokenResponse.getExpires_in().intValue();
|
int expiry = tokenResponse.getExpires_in().intValue();
|
||||||
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
|
securityHelper.addAccessCookies(response, token.getValue(), expiry);
|
||||||
response.addCookie(accessCookie);
|
|
||||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||||
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
|
|
@ -291,8 +287,6 @@ public class EsiaAuthService {
|
||||||
authenticationManager.authenticate(jwtAuthentication);
|
authenticationManager.authenticate(jwtAuthentication);
|
||||||
context.setAuthentication(jwtAuthentication);
|
context.setAuthentication(jwtAuthentication);
|
||||||
SecurityContextHolder.setContext(context);
|
SecurityContextHolder.setContext(context);
|
||||||
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
|
|
||||||
response.addCookie(authMarkerCookie);
|
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
@ -338,12 +332,12 @@ public class EsiaAuthService {
|
||||||
EsiaTokensStore.removeAccessToken(userId);
|
EsiaTokensStore.removeAccessToken(userId);
|
||||||
EsiaTokensStore.removeRefreshToken(userId);
|
EsiaTokensStore.removeRefreshToken(userId);
|
||||||
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
|
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
|
||||||
String redirectUrl = esiaConfig.getRedirectUrl();
|
String redirectUrl = esiaConfig.getLogoutRedirectUrl();
|
||||||
URL url = new URL(logoutUrl);
|
URL url = new URL(logoutUrl);
|
||||||
Map<String, String> params = mapOf(
|
Map<String, String> params = mapOf(
|
||||||
"client_id", esiaConfig.getClientId(),
|
"client_id", esiaConfig.getClientId(),
|
||||||
"redirect_url", redirectUrl);
|
"redirect_url", redirectUrl);
|
||||||
return makeRequest(url, params);
|
return buildUrl(url, params);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,89 @@
|
||||||
package ru.micord.ervu.security.webbpm.jwt.helper;
|
package ru.micord.ervu.security.webbpm.jwt.helper;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import java.net.IDN;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.ResponseCookie;
|
||||||
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
|
||||||
|
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
|
||||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_MARKER;
|
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_MARKER;
|
||||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_TOKEN;
|
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_TOKEN;
|
||||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.createCookie;
|
|
||||||
|
|
||||||
public final class SecurityHelper {
|
public final class SecurityHelper {
|
||||||
@Value("${cookie.path:#{null}}")
|
@Value("${cookie.path:#{null}}")
|
||||||
private String accessCookiePath;
|
private String accessCookiePath;
|
||||||
|
@Value("${cookie.domain:#{null}}")
|
||||||
|
private String accessCookieDomain;
|
||||||
|
@Value("${cookie.secure:false}")
|
||||||
|
private boolean accessCookieSecure;
|
||||||
|
@Value("${cookie.same.site:Lax}")
|
||||||
|
private String accessCookieSameSite;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void init() {
|
||||||
|
|
||||||
|
if (accessCookieDomain != null) {
|
||||||
|
accessCookieDomain = IDN.toASCII(accessCookieDomain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void clearAccessCookies(HttpServletResponse response) {
|
public void clearAccessCookies(HttpServletResponse response) {
|
||||||
Cookie tokenCookie = createCookie(AUTH_TOKEN, null, null);
|
ResponseCookie emptyAuthToken = createCookie(AUTH_TOKEN, null, accessCookiePath)
|
||||||
tokenCookie.setMaxAge(0);
|
.maxAge(0).build();
|
||||||
tokenCookie.setPath(accessCookiePath);
|
addResponseCookie(response, emptyAuthToken);
|
||||||
tokenCookie.setHttpOnly(true);
|
|
||||||
response.addCookie(tokenCookie);
|
|
||||||
|
|
||||||
Cookie markerCookie = createCookie(AUTH_MARKER, null, null);
|
ResponseCookie emptyAuthMarker = createCookie(AUTH_MARKER, null, "/")
|
||||||
markerCookie.setMaxAge(0);
|
.maxAge(0)
|
||||||
markerCookie.setPath("/");
|
.secure(false)
|
||||||
response.addCookie(markerCookie);
|
.httpOnly(false)
|
||||||
|
.build();
|
||||||
|
addResponseCookie(response, emptyAuthMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cookie createAccessCookie(String cookieValue, int expiry) {
|
private void addResponseCookie(HttpServletResponse response, ResponseCookie cookie) {
|
||||||
Cookie authToken = createCookie(SecurityUtil.AUTH_TOKEN, cookieValue, accessCookiePath);
|
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||||
authToken.setPath(accessCookiePath);
|
|
||||||
authToken.setMaxAge(expiry);
|
|
||||||
return authToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cookie createAuthMarkerCookie(String cookieValue, int expiry) {
|
public void addAccessCookies(HttpServletResponse response, String cookieValue, int expiry) {
|
||||||
Cookie marker = createCookie(AUTH_MARKER, cookieValue, "/");
|
ResponseCookie authTokenCookie = createCookie(AUTH_TOKEN, cookieValue, accessCookiePath)
|
||||||
marker.setMaxAge(expiry);
|
.maxAge(expiry)
|
||||||
marker.setHttpOnly(false);
|
.build();
|
||||||
return marker;
|
addResponseCookie(response, authTokenCookie);
|
||||||
|
|
||||||
|
ResponseCookie authMarker = createCookie(AUTH_MARKER, "true", "/")
|
||||||
|
.maxAge(expiry)
|
||||||
|
.secure(false)
|
||||||
|
.httpOnly(false)
|
||||||
|
.build();
|
||||||
|
addResponseCookie(response, authMarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseCookie.ResponseCookieBuilder createCookie(String name, String value, String path) {
|
||||||
|
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||||
|
|
||||||
|
if (requestAttributes == null) {
|
||||||
|
throw new IllegalStateException("Must be called only in request context");
|
||||||
|
}
|
||||||
|
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(
|
||||||
|
REFERENCE_REQUEST);
|
||||||
|
|
||||||
|
if (request == null) {
|
||||||
|
throw new IllegalStateException("Must be called only in request context");
|
||||||
|
}
|
||||||
|
String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : "";
|
||||||
|
return ResponseCookie.from(name, cookieValue)
|
||||||
|
.path(path != null ? path : request.getContextPath())
|
||||||
|
.httpOnly(true)
|
||||||
|
.domain(accessCookieDomain)
|
||||||
|
.secure(accessCookieSecure)
|
||||||
|
.sameSite(accessCookieSameSite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
package ru.micord.ervu.security.webbpm.jwt.util;
|
package ru.micord.ervu.security.webbpm.jwt.util;
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
|
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
|
||||||
|
|
||||||
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
|
|
||||||
|
|
||||||
public final class SecurityUtil {
|
public final class SecurityUtil {
|
||||||
public static final String AUTH_TOKEN = "auth_token";
|
public static final String AUTH_TOKEN = "auth_token";
|
||||||
|
|
||||||
|
|
@ -23,24 +17,6 @@ public final class SecurityUtil {
|
||||||
//empty
|
//empty
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cookie createCookie(String name, String value, String path) {
|
|
||||||
String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : null;
|
|
||||||
Cookie cookie = new Cookie(name, cookieValue);
|
|
||||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
|
||||||
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(
|
|
||||||
REFERENCE_REQUEST);
|
|
||||||
|
|
||||||
if (path != null) {
|
|
||||||
cookie.setPath(path);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cookie.setPath(request.getContextPath());
|
|
||||||
}
|
|
||||||
cookie.setHttpOnly(true);
|
|
||||||
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String extractAuthToken(HttpServletRequest httpRequest) {
|
public static String extractAuthToken(HttpServletRequest httpRequest) {
|
||||||
Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN);
|
Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN);
|
||||||
return cookie != null ? cookie.getValue() : null;
|
return cookie != null ? cookie.getValue() : null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ru.micord.ervu.service;
|
||||||
|
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import org.apache.kafka.common.utils.Bytes;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import proto.ervu.rp.summons.SummonsResponseData;
|
||||||
|
import ru.micord.ervu.converter.SummonsResponseDataConverter;
|
||||||
|
import ru.micord.ervu.dto.SubpoenaRequestDto;
|
||||||
|
import ru.micord.ervu.dto.SubpoenaResponseDto;
|
||||||
|
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||||
|
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SubpoenaService {
|
||||||
|
|
||||||
|
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
|
||||||
|
private final SummonsResponseDataConverter converter;
|
||||||
|
|
||||||
|
@Value("${ervu.kafka.recruit.request.topic}")
|
||||||
|
private String recruitRequestTopic;
|
||||||
|
@Value("${ervu.kafka.recruit.reply.topic}")
|
||||||
|
private String recruitReplyTopic;
|
||||||
|
|
||||||
|
public SubpoenaService(
|
||||||
|
@Qualifier("recruit") ReplyingKafkaService<Object, Bytes> replyingKafkaService,
|
||||||
|
SummonsResponseDataConverter converter) {
|
||||||
|
this.replyingKafkaService = replyingKafkaService;
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubpoenaResponseDto getSubpoenaData() {
|
||||||
|
String ervuId = SecurityUtil.getErvuId();
|
||||||
|
|
||||||
|
if (ervuId == null) {
|
||||||
|
return new SubpoenaResponseDto.Builder().build();
|
||||||
|
}
|
||||||
|
SubpoenaRequestDto subpoenaRequestDto = new SubpoenaRequestDto(ervuId);
|
||||||
|
byte[] reply = replyingKafkaService.sendMessageAndGetReply(recruitRequestTopic,
|
||||||
|
recruitReplyTopic, subpoenaRequestDto).get();
|
||||||
|
|
||||||
|
try {
|
||||||
|
SummonsResponseData responseData = SummonsResponseData.parseFrom(reply);
|
||||||
|
return converter.convert(responseData);
|
||||||
|
}
|
||||||
|
catch (InvalidProtocolBufferException e) {
|
||||||
|
throw new RuntimeException("Failed to parse data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,9 @@ package ru.micord.ervu.service.rpc;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import model.FieldData;
|
import model.FieldData;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import ru.micord.ervu.dto.SubpoenaResponseDto;
|
||||||
|
import ru.micord.ervu.service.SubpoenaService;
|
||||||
import service.container.FormService;
|
import service.container.FormService;
|
||||||
|
|
||||||
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
|
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
|
||||||
|
|
@ -19,8 +22,13 @@ public class LoadFormRpcService extends Behavior {
|
||||||
@NotNull
|
@NotNull
|
||||||
public FormService formService;
|
public FormService formService;
|
||||||
|
|
||||||
|
//todo: Remove this shit
|
||||||
|
@Autowired
|
||||||
|
public SubpoenaService subpoenaService;
|
||||||
|
|
||||||
@RpcCall
|
@RpcCall
|
||||||
public List<FieldData> loadData(Object dto) {
|
public List<FieldData> loadData() {
|
||||||
return formService.loadData(dto);
|
SubpoenaResponseDto subpoenaData = subpoenaService.getSubpoenaData();
|
||||||
|
return formService.loadData(subpoenaData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -760,6 +760,10 @@ JBPM использует 3 корневых категории логирова
|
||||||
Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
|
Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
|
||||||
> - https://lkul.ervu.loc/ - правильное значение параметра
|
> - https://lkul.ervu.loc/ - правильное значение параметра
|
||||||
> - https://lkul.ervu.loc - неправильное значение параметра
|
> - https://lkul.ervu.loc - неправильное значение параметра
|
||||||
|
- `ESIA_LOGOUT_REDIRECT_URL` - ссылка, по которой должен быть направлен пользователь после logout-a
|
||||||
|
Важно: `ESIA_LOGOUT_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
|
||||||
|
> - https://lkul.ervu.loc/home.html - правильное значение параметра
|
||||||
|
> - https://lkul.ervu.loc - неправильное значение параметра
|
||||||
|
|
||||||
- `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА
|
- `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА
|
||||||
- `ESIA_CLIENT_CERT_HASH` - параметр, содержащий хэш сертификата (fingerprint сертификата) системы-клиента в hex–формате
|
- `ESIA_CLIENT_CERT_HASH` - параметр, содержащий хэш сертификата (fingerprint сертификата) системы-клиента в hex–формате
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ ESIA_BASE_URI=https://esia-portal1.test.gosuslugi.ru/
|
||||||
ESIA_CLIENT_ID=MNSV89
|
ESIA_CLIENT_ID=MNSV89
|
||||||
ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD
|
ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD
|
||||||
ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/
|
ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/
|
||||||
|
ESIA_LOGOUT_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/home.html
|
||||||
|
|
||||||
SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign
|
SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||||
<artifactId>fl</artifactId>
|
<artifactId>fl</artifactId>
|
||||||
<version>1.9.3-SNAPSHOT</version>
|
<version>1.9.4-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
<title>Личный кабинет физ.лица</title>
|
<title>Личный кабинет физ.лица</title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta http-equiv="Content-Security-Policy"
|
||||||
|
content="default-src 'self'; script-src 'self'; style-src 'unsafe-inline' 'self' data:; font-src 'self' data:; img-src 'self' data:"/>
|
||||||
|
<meta name="referrer" content="strict-origin-when-cross-origin"/>
|
||||||
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
|
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
|
||||||
</head>
|
</head>
|
||||||
<body webbpm class="webbpm ervu_lkrp_fl">
|
<body webbpm class="webbpm ervu_lkrp_fl">
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||||
<artifactId>fl</artifactId>
|
<artifactId>fl</artifactId>
|
||||||
<version>1.9.3-SNAPSHOT</version>
|
<version>1.9.4-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
|
<form #logoutForm method="post" [action]="formAction" hidden style="display: none">
|
||||||
|
<input type="hidden" name="_csrf" [value]="csrfValue"/>
|
||||||
|
</form>
|
||||||
<button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button>
|
<button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button>
|
||||||
<div ngbDropdownMenu *ngIf="getIsAuth()">
|
<div ngbDropdownMenu *ngIf="getIsAuth()">
|
||||||
<a routerLink="/mydata" class="data">Мои данные</a>
|
<a routerLink="/mydata" class="data">Мои данные</a>
|
||||||
<button ngbDropdownItem class="exit" (click)="logout()">Выйти</button>
|
<button ngbDropdownItem class="exit" (click)="logoutForm.submit()">Выйти</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="exit" *ngIf="!getIsAuth()" (click)="logout()">Выйти</button>
|
<button class="exit" *ngIf="!getIsAuth()" (click)="logoutForm.submit()">Выйти</button>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import {Form} from "@webbpm/base-package";
|
import {Form} from "@webbpm/base-package";
|
||||||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||||
import {ErvuDataService} from "../../../modules/app/service/ervu-data.service";
|
import {ErvuDataService} from "../../../modules/app/service/ervu-data.service";
|
||||||
import {Subscription} from "rxjs";
|
|
||||||
import {LoadFormRpcService} from "../../../generated/ru/micord/ervu/service/rpc/LoadFormRpcService";
|
import {LoadFormRpcService} from "../../../generated/ru/micord/ervu/service/rpc/LoadFormRpcService";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -14,25 +13,16 @@ export class LoadForm extends Form {
|
||||||
|
|
||||||
private formRpcService: LoadFormRpcService;
|
private formRpcService: LoadFormRpcService;
|
||||||
private ervuDataService: ErvuDataService;
|
private ervuDataService: ErvuDataService;
|
||||||
private subscription: Subscription;
|
|
||||||
|
|
||||||
private valuesData: string;
|
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
super.initialize();
|
super.initialize();
|
||||||
this.formRpcService = this.getScript(LoadFormRpcService);
|
this.formRpcService = this.getScript(LoadFormRpcService);
|
||||||
this.ervuDataService = this.injector.get(ErvuDataService);
|
this.ervuDataService = this.injector.get(ErvuDataService);
|
||||||
this.subscription = this.ervuDataService.message.subscribe(value => {
|
|
||||||
if (value) {
|
|
||||||
this.valuesData = value;
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData(): Promise<any> {
|
loadData(): Promise<any> {
|
||||||
return this.formRpcService
|
return this.formRpcService
|
||||||
.loadData(this.valuesData)
|
.loadData()
|
||||||
.then(fieldDataList => this.setData(fieldDataList))
|
.then(fieldDataList => this.setData(fieldDataList))
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
throw new Error(reason);
|
throw new Error(reason);
|
||||||
|
|
@ -49,6 +39,5 @@ export class LoadForm extends Form {
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
super.ngOnDestroy();
|
super.ngOnDestroy();
|
||||||
this.subscription.unsubscribe();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,45 @@
|
||||||
import {ChangeDetectorRef, Component, OnInit} from "@angular/core";
|
import {ChangeDetectorRef, Component, DoCheck, OnInit} from "@angular/core";
|
||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient, HttpXsrfTokenExtractor} from "@angular/common/http";
|
||||||
import {CookieService} from "ngx-cookie";
|
import {CookieService} from "ngx-cookie";
|
||||||
|
import {AppConfigService} from "@webbpm/base-package";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
moduleId: module.id,
|
moduleId: module.id,
|
||||||
selector: "[log-out]",
|
selector: "[log-out]",
|
||||||
templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
|
templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
|
||||||
})
|
})
|
||||||
export class LogOutComponent implements OnInit{
|
export class LogOutComponent implements OnInit, DoCheck{
|
||||||
|
private static readonly BACKEND_URL: string = "backend.url";
|
||||||
|
private static readonly BACKEND_CONTEXT: string = "backend.context";
|
||||||
|
private static readonly LOGOUT_URL_POSTFIX: string = "/esia/logout";
|
||||||
|
|
||||||
private userFullname: string;
|
private userFullname: string;
|
||||||
|
csrfValue: any;
|
||||||
|
formAction: any;
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient,
|
constructor(private httpClient: HttpClient,
|
||||||
private cookieService: CookieService, private cd: ChangeDetectorRef) {
|
private cookieService: CookieService,
|
||||||
|
private appConfigService: AppConfigService,
|
||||||
|
private tokenExtractor: HttpXsrfTokenExtractor,
|
||||||
|
private cd: ChangeDetectorRef) {
|
||||||
|
let backendUrl = this.appConfigService.getParamValue(LogOutComponent.BACKEND_URL);
|
||||||
|
let backendContext = this.appConfigService.getParamValue(
|
||||||
|
LogOutComponent.BACKEND_CONTEXT);
|
||||||
|
|
||||||
|
if (backendUrl) {
|
||||||
|
this.formAction = `${backendUrl}${LogOutComponent.LOGOUT_URL_POSTFIX}`;
|
||||||
|
}
|
||||||
|
else if (backendContext) {
|
||||||
|
this.formAction = `/${backendContext}${LogOutComponent.LOGOUT_URL_POSTFIX}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngDoCheck(): void {
|
||||||
|
this.csrfValue = this.tokenExtractor.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.csrfValue = this.tokenExtractor.getToken();
|
||||||
let isAuth = this.getIsAuth();
|
let isAuth = this.getIsAuth();
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
|
|
@ -27,12 +51,6 @@ export class LogOutComponent implements OnInit{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): Promise<any> {
|
|
||||||
return this.httpClient.post<string>('esia/logout', {}, { responseType: 'text' as 'json' }).toPromise().then(url => {
|
|
||||||
window.open(url, "_self");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public getUserFullname(): string {
|
public getUserFullname(): string {
|
||||||
return this.userFullname;
|
return this.userFullname;
|
||||||
}
|
}
|
||||||
|
|
@ -40,4 +58,4 @@ export class LogOutComponent implements OnInit{
|
||||||
public getIsAuth(): boolean {
|
public getIsAuth(): boolean {
|
||||||
return this.cookieService.get("webbpm.ervu-lkrp-fl") != null;
|
return this.cookieService.get("webbpm.ervu-lkrp-fl") != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
pom.xml
2
pom.xml
|
|
@ -4,7 +4,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||||
<artifactId>fl</artifactId>
|
<artifactId>fl</artifactId>
|
||||||
<version>1.9.3-SNAPSHOT</version>
|
<version>1.9.4-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>backend</module>
|
<module>backend</module>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||||
<artifactId>fl</artifactId>
|
<artifactId>fl</artifactId>
|
||||||
<version>1.9.3-SNAPSHOT</version>
|
<version>1.9.4-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue