WebSocket is closed before the connection is established
не все так плохо как есть на самом деле у меня один раз websocket подключается а если перегрузить страницу или зайти в нову вкладку то может не соединить, но если пару раз перезайти то может и соединить Вот конфиг на webSocket
package greencity.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.DefaultContentTypeResolver;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import java.util.List;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(final MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setObjectMapper(new ObjectMapper());
converter.setContentTypeResolver(resolver);
messageConverters.add(converter);
return false;
}
}
accessfilter
package greencity.security.filters;
import greencity.dto.user.UserVO;
import greencity.security.jwt.JwtTool;
import greencity.service.UserService;
import io.jsonwebtoken.ExpiredJwtException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* Class that provide Authentication object based on JWT.
*
* @author Yurii Koval.
* @version 1.0
*/
@Slf4j
public class AccessTokenAuthenticationFilter extends OncePerRequestFilter {
private final JwtTool jwtTool;
private final AuthenticationManager authenticationManager;
private final UserService userService;
/**
* Constructor.
*/
public AccessTokenAuthenticationFilter(JwtTool jwtTool, AuthenticationManager authenticationManager,
UserService userService) {
this.jwtTool = jwtTool;
this.authenticationManager = authenticationManager;
this.userService = userService;
}
private String getTokenFromCookies(Cookie[] cookies) {
return Arrays.stream(cookies)
.filter(c -> c.getName().equals("accessToken"))
.findFirst()
.map(Cookie::getValue).orElse(null);
}
private String extractToken(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
String uri = request.getRequestURI();
if (cookies != null && uri.startsWith("/management")) {
return getTokenFromCookies(cookies);
}
return jwtTool.getTokenFromHttpServletRequest(request);
}
/**
* Checks if request has token in header, if this token still valid, and set
* authentication for spring.
*
* @param request this is servlet that take request
* @param response this is response servlet
* @param chain this is filter of chain
*/
@Override
public void doFilterInternal(@SuppressWarnings("NullableProblems") HttpServletRequest request,
@SuppressWarnings("NullableProblems") HttpServletResponse response,
@SuppressWarnings("NullableProblems") FilterChain chain)
throws IOException, ServletException {
String token = extractToken(request);
if (token != null) {
try {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(token, null));
Optional<UserVO> user = userService.findNotDeactivatedByEmail((String) authentication.getPrincipal());
if (user.isPresent()) {
log.debug("User successfully authenticate - {}", authentication.getPrincipal());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (ExpiredJwtException e) {
log.info("Token has expired: " + token);
} catch (Exception e) {
log.info("Access denied with token: " + e.getMessage());
}
}
chain.doFilter(request, response);
}
}
и сам токен который прокидывается
package greencity.security.jwt;
import static greencity.constant.AppConstant.AUTHORITIES;
import greencity.dto.user.UserVO;
import greencity.enums.Role;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultJwtParser;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* Class that provides methods for working with JWT.
*
* @author Nazar Stasyuk && Yurii Koval.
* @version 2.0
*/
@Slf4j
@Component
public class JwtTool {
private final Integer accessTokenValidTimeInMinutes;
private final Integer refreshTokenValidTimeInMinutes;
private final String accessTokenKey;
/**
* Constructor.
*/
@Autowired
public JwtTool(@Value("${accessTokenValidTimeInMinutes}") Integer accessTokenValidTimeInMinutes,
@Value("${refreshTokenValidTimeInMinutes}") Integer refreshTokenValidTimeInMinutes,
@Value("${tokenKey}") String accessTokenKey) {
this.accessTokenValidTimeInMinutes = accessTokenValidTimeInMinutes;
this.refreshTokenValidTimeInMinutes = refreshTokenValidTimeInMinutes;
this.accessTokenKey = accessTokenKey;
}
/**
* Method for creating access token.
*
* @param email this is email of user.
* @param role this is role of user.
*/
public String createAccessToken(String email, Role role) {
Claims claims = Jwts.claims().setSubject(email);
claims.put(AUTHORITIES, Collections.singleton(role.name()));
Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.add(Calendar.MINUTE, accessTokenValidTimeInMinutes);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(calendar.getTime())
.signWith(SignatureAlgorithm.HS256, accessTokenKey)
.compact();
}
/**
* Method for creating access token.
*
* @param user - entity {@link UserVO}
*/
public String createRefreshToken(UserVO user) {
Claims claims = Jwts.claims().setSubject(user.getEmail());
claims.put(AUTHORITIES, Collections.singleton(user.getRole().name()));
Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.add(Calendar.MINUTE, refreshTokenValidTimeInMinutes);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(calendar.getTime())
.signWith(SignatureAlgorithm.HS256, user.getRefreshTokenKey())
.compact();
}
/**
* Gets email from token and throws an error if token is expired. WARNING: The
* method DOESN'T CHECK whether the token's signature is valid.
*
* @param token - access token
* @return - user's email
* @throws io.jsonwebtoken.ExpiredJwtException - if token is expired.
*/
public String getEmailOutOfAccessToken(String token) {
String[] splitToken = token.split("\\.");
String unsignedToken = splitToken[0] + "." + splitToken[1] + ".";
DefaultJwtParser parser = new DefaultJwtParser();
Jwt<?, ?> jwt = parser.parse(unsignedToken);
return ((Claims) jwt.getBody()).getSubject();
}
/**
* Method that check if token still valid.
*
* @param token this is token.
* @return {@link Boolean}
*/
public boolean isTokenValid(String token, String tokenKey) {
boolean isValid = false;
try {
Jwts.parser().setSigningKey(tokenKey).parseClaimsJws(token);
isValid = true;
} catch (Exception e) {
log.info("Given token is not valid: " + e.getMessage());
}
return isValid;
}
/**
* Returns access token key.
*
* @return accessTokenKey
*/
public String getAccessTokenKey() {
return accessTokenKey;
}
/**
* Method that get token from {@link HttpServletRequest}.
*
* @param servletRequest this is your request.
* @return {@link String} of token or null.
*/
public String getTokenFromHttpServletRequest(HttpServletRequest servletRequest) {
return Optional
.ofNullable(servletRequest.getHeader("Authorization"))
.filter(authHeader -> authHeader.startsWith("Bearer "))
.map(token -> token.substring(7))
.orElse(null);
}
/**
* Generates a random string that can be used as refresh token key.
*
* @return random generated token key
*/
public String generateTokenKey() {
return UUID.randomUUID().toString();
}
}
А к всему этому еще могу прикрепить гитхаб ссылку
https://github.com/ita-social-projects/GreenCity
и фото проблемы
