Обновил версии библиотек. Заменил устаревшие подходы на современные.
This commit is contained in:
parent
6a3ea3f134
commit
3db2b2dafd
43
pom.xml
43
pom.xml
@ -5,43 +5,64 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.5.3</version>
|
<version>2.7.0</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>org.sadtech.example.jwt</groupId>
|
|
||||||
|
<groupId>dev.struchkiov.example</groupId>
|
||||||
<artifactId>server-jwt</artifactId>
|
<artifactId>server-jwt</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
<name>server-jwt</name>
|
<name>server-jwt</name>
|
||||||
<description>server-jwt</description>
|
<description>server-jwt</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>11</java.version>
|
<java.version>17</java.version>
|
||||||
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt</artifactId>
|
<artifactId>jjwt-api</artifactId>
|
||||||
<version>0.9.1</version>
|
<version>0.11.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.xml.bind</groupId>
|
<groupId>javax.xml.bind</groupId>
|
||||||
<artifactId>jaxb-api</artifactId>
|
<artifactId>jaxb-api</artifactId>
|
||||||
<version>2.4.0-b180830.0359</version>
|
<version>2.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server;
|
package dev.struchkov.example.jwt.server;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -0,0 +1,38 @@
|
|||||||
|
package dev.struchkov.example.jwt.server.config;
|
||||||
|
|
||||||
|
import dev.struchkov.example.jwt.server.filter.JwtFilter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
private final JwtFilter jwtFilter;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
return http
|
||||||
|
.httpBasic().disable()
|
||||||
|
.csrf().disable()
|
||||||
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
.authorizeHttpRequests(
|
||||||
|
authz -> authz
|
||||||
|
.antMatchers("/api/auth/login", "/api/auth/token").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
.and()
|
||||||
|
.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
|
).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package org.sadtech.example.jwt.server.controller;
|
package dev.struchkov.example.jwt.server.controller;
|
||||||
|
|
||||||
|
import dev.struchkov.example.jwt.server.domain.JwtResponse;
|
||||||
|
import dev.struchkov.example.jwt.server.domain.RefreshJwtRequest;
|
||||||
|
import dev.struchkov.example.jwt.server.service.AuthService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtRequest;
|
import dev.struchkov.example.jwt.server.domain.JwtRequest;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtResponse;
|
|
||||||
import org.sadtech.example.jwt.server.domain.RefreshJwtRequest;
|
|
||||||
import org.sadtech.example.jwt.server.service.AuthService;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
@ -1,8 +1,8 @@
|
|||||||
package org.sadtech.example.jwt.server.controller;
|
package dev.struchkov.example.jwt.server.controller;
|
||||||
|
|
||||||
|
import dev.struchkov.example.jwt.server.service.AuthService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtAuthentication;
|
import dev.struchkov.example.jwt.server.domain.JwtAuthentication;
|
||||||
import org.sadtech.example.jwt.server.service.AuthService;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -20,7 +20,6 @@ public class Controller {
|
|||||||
@GetMapping("hello/user")
|
@GetMapping("hello/user")
|
||||||
public ResponseEntity<String> helloUser() {
|
public ResponseEntity<String> helloUser() {
|
||||||
final JwtAuthentication authInfo = authService.getAuthInfo();
|
final JwtAuthentication authInfo = authService.getAuthInfo();
|
||||||
|
|
||||||
return ResponseEntity.ok("Hello user " + authInfo.getPrincipal() + "!");
|
return ResponseEntity.ok("Hello user " + authInfo.getPrincipal() + "!");
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
@ -1,4 +1,4 @@
|
|||||||
package org.sadtech.example.jwt.server.domain;
|
package dev.struchkov.example.jwt.server.domain;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -9,8 +9,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class User {
|
public class User {
|
||||||
|
|
||||||
private String login;
|
private String login;
|
@ -0,0 +1,14 @@
|
|||||||
|
package dev.struchkov.example.jwt.server.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Исключение используется для ошибок аутентификации и авторизациит.
|
||||||
|
*
|
||||||
|
* @author upagge 21.06.2022
|
||||||
|
*/
|
||||||
|
public class AuthException extends RuntimeException {
|
||||||
|
|
||||||
|
public AuthException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package org.sadtech.example.jwt.server.filter;
|
package dev.struchkov.example.jwt.server.filter;
|
||||||
|
|
||||||
|
import dev.struchkov.example.jwt.server.service.JwtProvider;
|
||||||
|
import dev.struchkov.example.jwt.server.service.JwtUtils;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtAuthentication;
|
import dev.struchkov.example.jwt.server.domain.JwtAuthentication;
|
||||||
import org.sadtech.example.jwt.server.service.JwtProvider;
|
|
||||||
import org.sadtech.example.jwt.server.service.JwtUtils;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
@ -1,13 +1,13 @@
|
|||||||
package org.sadtech.example.jwt.server.service;
|
package dev.struchkov.example.jwt.server.service;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtAuthentication;
|
import dev.struchkov.example.jwt.server.domain.JwtAuthentication;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtRequest;
|
import dev.struchkov.example.jwt.server.domain.JwtRequest;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtResponse;
|
import dev.struchkov.example.jwt.server.domain.JwtResponse;
|
||||||
import org.sadtech.example.jwt.server.domain.User;
|
import dev.struchkov.example.jwt.server.domain.User;
|
||||||
import org.sadtech.example.jwt.server.exception.AuthException;
|
import dev.struchkov.example.jwt.server.exception.AuthException;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -1,18 +1,21 @@
|
|||||||
package org.sadtech.example.jwt.server.service;
|
package dev.struchkov.example.jwt.server.service;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.MalformedJwtException;
|
import io.jsonwebtoken.MalformedJwtException;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.SignatureException;
|
|
||||||
import io.jsonwebtoken.UnsupportedJwtException;
|
import io.jsonwebtoken.UnsupportedJwtException;
|
||||||
|
import io.jsonwebtoken.io.Decoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import io.jsonwebtoken.security.SignatureException;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.sadtech.example.jwt.server.domain.User;
|
import dev.struchkov.example.jwt.server.domain.User;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.security.Key;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
@ -22,54 +25,55 @@ import java.util.Date;
|
|||||||
@Component
|
@Component
|
||||||
public class JwtProvider {
|
public class JwtProvider {
|
||||||
|
|
||||||
private final String jwtAccessSecret;
|
private final SecretKey jwtAccessSecret;
|
||||||
private final String jwtRefreshSecret;
|
private final SecretKey jwtRefreshSecret;
|
||||||
|
|
||||||
public JwtProvider(
|
public JwtProvider(
|
||||||
@Value("${jwt.secret.access}") String jwtAccessSecret,
|
@Value("${jwt.secret.access}") String jwtAccessSecret,
|
||||||
@Value("${jwt.secret.refresh}") String jwtRefreshSecret
|
@Value("${jwt.secret.refresh}") String jwtRefreshSecret
|
||||||
) {
|
) {
|
||||||
this.jwtAccessSecret = jwtAccessSecret;
|
this.jwtAccessSecret = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtAccessSecret));
|
||||||
this.jwtRefreshSecret = jwtRefreshSecret;
|
this.jwtRefreshSecret = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtRefreshSecret));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateAccessToken(@NonNull User user) {
|
public String generateAccessToken(@NonNull User user) {
|
||||||
final LocalDateTime now = LocalDateTime.now();
|
final LocalDateTime now = LocalDateTime.now();
|
||||||
final Instant accessExpirationInstant = now.plusMinutes(5).atZone(ZoneId.systemDefault()).toInstant();
|
final Instant accessExpirationInstant = now.plusMinutes(5).atZone(ZoneId.systemDefault()).toInstant();
|
||||||
final Date accessExpiration = Date.from(accessExpirationInstant);
|
final Date accessExpiration = Date.from(accessExpirationInstant);
|
||||||
final String accessToken = Jwts.builder()
|
return Jwts.builder()
|
||||||
.setSubject(user.getLogin())
|
.setSubject(user.getLogin())
|
||||||
.setExpiration(accessExpiration)
|
.setExpiration(accessExpiration)
|
||||||
.signWith(SignatureAlgorithm.HS512, jwtAccessSecret)
|
.signWith(jwtAccessSecret)
|
||||||
.claim("roles", user.getRoles())
|
.claim("roles", user.getRoles())
|
||||||
.claim("firstName", user.getFirstName())
|
.claim("firstName", user.getFirstName())
|
||||||
.compact();
|
.compact();
|
||||||
return accessToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateRefreshToken(@NonNull User user) {
|
public String generateRefreshToken(@NonNull User user) {
|
||||||
final LocalDateTime now = LocalDateTime.now();
|
final LocalDateTime now = LocalDateTime.now();
|
||||||
final Instant refreshExpirationInstant = now.plusDays(30).atZone(ZoneId.systemDefault()).toInstant();
|
final Instant refreshExpirationInstant = now.plusDays(30).atZone(ZoneId.systemDefault()).toInstant();
|
||||||
final Date refreshExpiration = Date.from(refreshExpirationInstant);
|
final Date refreshExpiration = Date.from(refreshExpirationInstant);
|
||||||
final String refreshToken = Jwts.builder()
|
return Jwts.builder()
|
||||||
.setSubject(user.getLogin())
|
.setSubject(user.getLogin())
|
||||||
.setExpiration(refreshExpiration)
|
.setExpiration(refreshExpiration)
|
||||||
.signWith(SignatureAlgorithm.HS512, jwtRefreshSecret)
|
.signWith(jwtRefreshSecret)
|
||||||
.compact();
|
.compact();
|
||||||
return refreshToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateAccessToken(@NonNull String token) {
|
public boolean validateAccessToken(@NonNull String accessToken) {
|
||||||
return validateToken(token, jwtAccessSecret);
|
return validateToken(accessToken, jwtAccessSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean validateRefreshToken(@NonNull String token) {
|
public boolean validateRefreshToken(@NonNull String refreshToken) {
|
||||||
return validateToken(token, jwtRefreshSecret);
|
return validateToken(refreshToken, jwtRefreshSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateToken(@NonNull String token, @NonNull String secret) {
|
private boolean validateToken(@NonNull String token, @NonNull Key secret) {
|
||||||
try {
|
try {
|
||||||
Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
|
Jwts.parserBuilder()
|
||||||
|
.setSigningKey(secret)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token);
|
||||||
return true;
|
return true;
|
||||||
} catch (ExpiredJwtException expEx) {
|
} catch (ExpiredJwtException expEx) {
|
||||||
log.error("Token expired", expEx);
|
log.error("Token expired", expEx);
|
||||||
@ -93,8 +97,12 @@ public class JwtProvider {
|
|||||||
return getClaims(token, jwtRefreshSecret);
|
return getClaims(token, jwtRefreshSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Claims getClaims(@NonNull String token, @NonNull String secret) {
|
private Claims getClaims(@NonNull String token, @NonNull Key secret) {
|
||||||
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
|
return Jwts.parserBuilder()
|
||||||
|
.setSigningKey(secret)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package org.sadtech.example.jwt.server.service;
|
package dev.struchkov.example.jwt.server.service;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.sadtech.example.jwt.server.domain.JwtAuthentication;
|
import dev.struchkov.example.jwt.server.domain.JwtAuthentication;
|
||||||
import org.sadtech.example.jwt.server.domain.Role;
|
import dev.struchkov.example.jwt.server.domain.Role;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
@ -1,9 +1,9 @@
|
|||||||
package org.sadtech.example.jwt.server.service;
|
package dev.struchkov.example.jwt.server.service;
|
||||||
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.sadtech.example.jwt.server.domain.Role;
|
import dev.struchkov.example.jwt.server.domain.Role;
|
||||||
import org.sadtech.example.jwt.server.domain.User;
|
import dev.struchkov.example.jwt.server.domain.User;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
@ -0,0 +1,18 @@
|
|||||||
|
package dev.struchkov.example.jwt.server.util;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.io.Encoders;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
|
||||||
|
public class GenerateKeys {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(generateKey());
|
||||||
|
System.out.println(generateKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateKey() {
|
||||||
|
return Encoders.BASE64.encode(Keys.secretKeyFor(SignatureAlgorithm.HS512).getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,44 +0,0 @@
|
|||||||
package org.sadtech.example.jwt.server.config;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.sadtech.example.jwt.server.filter.JwtFilter;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
private final JwtFilter jwtFilter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
|
||||||
http
|
|
||||||
.httpBasic().disable()
|
|
||||||
.csrf().disable()
|
|
||||||
.sessionManagement()
|
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
|
||||||
.and()
|
|
||||||
.authorizeRequests()
|
|
||||||
.antMatchers("/api/auth/login", "/api/auth/token").permitAll()
|
|
||||||
.anyRequest().authenticated()
|
|
||||||
.and()
|
|
||||||
.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new BCryptPasswordEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package org.sadtech.example.jwt.server.exception;
|
|
||||||
|
|
||||||
public class AuthException extends RuntimeException {
|
|
||||||
|
|
||||||
public AuthException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,2 +1,2 @@
|
|||||||
jwt.secret.access=supermegasecret
|
jwt.secret.access=qBTmv4oXFFR2GwjexDJ4t6fsIUIUhhXqlktXjXdkcyygs8nPVEwMfo29VDRRepYDVV5IkIxBMzr7OEHXEHd37w==
|
||||||
jwt.secret.refresh=supermegarefreshsecret
|
jwt.secret.refresh=zL1HB3Pch05Avfynovxrf/kpF9O2m4NCWKJUjEp27s9J2jEG3ifiKCGylaZ8fDeoONSTJP/wAzKawB8F9rOMNg==
|
327
src/main/resources/postman_collection.json
Normal file
327
src/main/resources/postman_collection.json
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"_postman_id": "7be0f05f-b637-4296-a2ab-9ae2e622fa16",
|
||||||
|
"name": "JWT",
|
||||||
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
|
"_exporter_id": "16442716"
|
||||||
|
},
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Auth Service",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Login User",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"login\": \"anton\",\n \"password\": \"1234\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/auth/login",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"login"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Login Admin",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"login\": \"anton\",\n \"password\": \"1234\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/auth/login",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"login"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get new access token",
|
||||||
|
"request": {
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"refreshToken\": \"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1ODM4NTcwMH0.35Xfw495acquYKcHKK2MrRU_dPlNqPQC7N3-vxA2d0zayWD1Ify6J-xYl5tWkm-8qdyXqPCri3uEfpzx1Lc7WA\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/auth/token",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Get new access and refresh tokens",
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1NTc5NDE2NCwicm9sZXMiOlsiVVNFUiJdLCJmaXJzdE5hbWUiOiLQkNC90YLQvtC9In0.hJ_j6BjysvP2Qv2Lt06m8FwE-U4AHRjVQ9BpBy6fJIycUDZxBSAhoeFucaOGFgukTMfICZbgEvna9OuwqYzzwQ",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"refreshToken\": \"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1ODM4NTg2NH0.gfE8Gr_1Sp_Um3vXG2EaDgqz6p9iLo1_wZgKksme13pg2q4cXVyShBtMTZ0ApfdcGzXcJ2MUoFHtTJCMj8ROUQ\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/auth/refresh",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"auth",
|
||||||
|
"refresh"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Service One",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Hello User Request",
|
||||||
|
"protocolProfileBehavior": {
|
||||||
|
"disableBodyPruning": true
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1NTc5NTEyMCwicm9sZXMiOlsiVVNFUiJdLCJmaXJzdE5hbWUiOiLQkNC90YLQvtC9In0.tLFtJ0oPLq493u7EJe2Tb4kLxAFGCYgIWrmMq1XiHNhihbh2sV9-yVQyXOFwIpArw4ReAuUoP-6F2B_6YYzx4Q",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/hello/user",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"hello",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hello Admin Request",
|
||||||
|
"protocolProfileBehavior": {
|
||||||
|
"disableBodyPruning": true
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1NTc5MzYxNiwicm9sZXMiOlsiVVNFUiJdLCJmaXJzdE5hbWUiOiLQkNC90YLQvtC9In0.2JBqOWBOmO9a93nwiBgFvf6LvATMw-DALRlSwjFbshhu5RP110NIg5Aod_V0r1WtNDAbuzsHFxk7N-chy4sHQg",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/api/hello/admin",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"hello",
|
||||||
|
"admin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Service Two",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "Hello User Request",
|
||||||
|
"protocolProfileBehavior": {
|
||||||
|
"disableBodyPruning": true
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8099/api/hello/user",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8099",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"hello",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hello Admin Request",
|
||||||
|
"protocolProfileBehavior": {
|
||||||
|
"disableBodyPruning": true
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhbnRvbiIsImV4cCI6MTY1NTc1NjQyNSwicm9sZXMiOlsiVVNFUiJdLCJmaXJzdE5hbWUiOiLQkNC90YLQvtC9In0.y40_c0QGAMzf3tq19UtfNHdYcU7KS_xCqzzxBDLeUMZ5ait7LfWbLv8hCHyKGNBHOYLuquu5ylTiNBT4DBgr3A",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8099/api/hello/user",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8099",
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"hello",
|
||||||
|
"user"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user