mirror of
https://github.com/fabioformosa/quartz-manager.git
synced 2026-01-01 23:23:31 +09:00
#6 step into security refactoring
This commit is contained in:
@@ -164,7 +164,12 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ 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;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||
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.builders.WebSecurity;
|
||||
@@ -14,16 +17,17 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler;
|
||||
import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler;
|
||||
import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
|
||||
import it.fabioformosa.quartzmanager.configuration.properties.InMemoryAccountProperties;
|
||||
import it.fabioformosa.quartzmanager.security.auth.LogoutSuccess;
|
||||
import it.fabioformosa.quartzmanager.security.auth.RestAuthenticationEntryPoint;
|
||||
import it.fabioformosa.quartzmanager.security.auth.TokenAuthenticationFilter;
|
||||
|
||||
/**
|
||||
@@ -37,91 +41,96 @@ import it.fabioformosa.quartzmanager.security.auth.TokenAuthenticationFilter;
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Value("${jwt.cookie}")
|
||||
private String TOKEN_COOKIE;
|
||||
private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui.html", "/v2/api-docs", "/swagger-resources/**", "/webjars/**"};
|
||||
|
||||
// @Autowired
|
||||
// private CustomUserDetailsService jwtUserDetailsService;
|
||||
@Value("${quartz-manager.security.jwt.cookie}")
|
||||
private String TOKEN_COOKIE;
|
||||
|
||||
@Autowired
|
||||
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
|
||||
// @Autowired
|
||||
// private CustomUserDetailsService jwtUserDetailsService;
|
||||
|
||||
@Autowired
|
||||
private LogoutSuccess logoutSuccess;
|
||||
@Autowired
|
||||
private LogoutSuccess logoutSuccess;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
@Autowired
|
||||
private LoginConfig loginConfigurer;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationFailureHandler authenticationFailureHandler;
|
||||
@Autowired
|
||||
private InMemoryAccountProperties inMemoryAccountProps;
|
||||
|
||||
@Value("${quartz-manager.account.user}")
|
||||
private String adminUser;
|
||||
// @Bean
|
||||
// @Override
|
||||
// public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
// return super.authenticationManagerBean();
|
||||
// }
|
||||
|
||||
@Value("${quartz-manager.account.pwd}")
|
||||
private String adminPwd;
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)throws Exception {
|
||||
configureInMemoryAuthentication(authenticationManagerBuilder);
|
||||
// authenticationManagerBuilder.userDetailsService(jwtUserDetailsService)
|
||||
// .passwordEncoder(passwordEncoder());
|
||||
}
|
||||
|
||||
// @Bean
|
||||
// @Override
|
||||
// public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
// return super.authenticationManagerBean();
|
||||
// }
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// http.csrf().ignoringAntMatchers("/api/login", "/api/signup") //
|
||||
// .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) //
|
||||
http.csrf().disable() //
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() //
|
||||
.exceptionHandling().authenticationEntryPoint(restAuthEntryPoint()).and()
|
||||
.addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class)
|
||||
.authorizeRequests().anyRequest().authenticated();
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/css/**", //
|
||||
"/js/**", //
|
||||
"/img/**", //
|
||||
"/lib/**", //
|
||||
"/swagger-resources/**", "/swagger-ui.html","/v2/api-docs", //
|
||||
"/webjars/**");
|
||||
}
|
||||
loginConfigurer.configureLoginHandler(http, authenticationManager()).logout().logoutRequestMatcher(new AntPathRequestMatcher("/api/logout"))
|
||||
.logoutSuccessHandler(logoutSuccess).deleteCookies(TOKEN_COOKIE);
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder)
|
||||
throws Exception {
|
||||
// authenticationManagerBuilder.userDetailsService(jwtUserDetailsService)
|
||||
// .passwordEncoder(passwordEncoder());
|
||||
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
authenticationManagerBuilder.inMemoryAuthentication().withUser(adminUser).password(encoder.encode(adminPwd)).roles("ADMIN");
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenAuthenticationFilter jwtAuthenticationTokenFilter() throws Exception {
|
||||
return new TokenAuthenticationFilter();
|
||||
}
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring()//
|
||||
.antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI) //
|
||||
.antMatchers(HttpMethod.GET,"/css/**", "/js/**", "/img/**", "/lib/**");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
return super.userDetailsServiceBean();
|
||||
}
|
||||
private void configureInMemoryAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
|
||||
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
if(inMemoryAccountProps.isEnabled() && inMemoryAccountProps.getUsers() != null && !inMemoryAccountProps.getUsers().isEmpty()) {
|
||||
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuth = authenticationManagerBuilder.inMemoryAuthentication();
|
||||
inMemoryAccountProps.getUsers()
|
||||
.forEach(u -> inMemoryAuth
|
||||
.withUser(u.getName())
|
||||
.password(encoder.encode(u.getPassword()))
|
||||
.roles(u.getRoles().toArray(new String[0])));
|
||||
}
|
||||
}
|
||||
|
||||
// @Bean
|
||||
// public PasswordEncoder passwordEncoder() {
|
||||
// return new BCryptPasswordEncoder();
|
||||
// }
|
||||
@Bean
|
||||
CorsConfigurationSource corsConfigurationSource() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// http.csrf().ignoringAntMatchers("/api/login", "/api/signup") //
|
||||
// .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) //
|
||||
http.csrf().disable() //
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() //
|
||||
.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint).and()
|
||||
.addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class)
|
||||
.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/api/login")
|
||||
.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler)
|
||||
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/api/logout"))
|
||||
.logoutSuccessHandler(logoutSuccess).deleteCookies(TOKEN_COOKIE);
|
||||
@Bean
|
||||
public TokenAuthenticationFilter jwtAuthenticationTokenFilter() throws Exception {
|
||||
return new TokenAuthenticationFilter();
|
||||
}
|
||||
|
||||
}
|
||||
// @Bean
|
||||
// public PasswordEncoder passwordEncoder() {
|
||||
// return new BCryptPasswordEncoder();
|
||||
// }
|
||||
|
||||
@Bean
|
||||
CorsConfigurationSource corsConfigurationSource() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
|
||||
return source;
|
||||
}
|
||||
@Bean
|
||||
public AuthenticationEntryPoint restAuthEntryPoint() {
|
||||
return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
return super.userDetailsServiceBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package it.fabioformosa.quartzmanager.configuration.helpers;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
public interface LoginConfig {
|
||||
|
||||
HttpSecurity configureLoginHandler(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package it.fabioformosa.quartzmanager.configuration.helpers.impl;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
|
||||
import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler;
|
||||
import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class FormLoginConfig implements LoginConfig {
|
||||
|
||||
private static final String API_LOGIN = "/api/login";
|
||||
|
||||
@Autowired
|
||||
private AuthenticationSuccessHandler authenticationSuccessHandler;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationFailureHandler authenticationFailureHandler;
|
||||
|
||||
@Override
|
||||
public HttpSecurity configureLoginHandler(
|
||||
HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
|
||||
return http.formLogin().loginPage(API_LOGIN).successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package it.fabioformosa.quartzmanager.configuration.helpers.impl;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import it.fabioformosa.quartzmanager.configuration.helpers.LoginConfig;
|
||||
import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.auth.JwtAuthenticationFilter;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "userpwd-filter-enabled", havingValue = "true", matchIfMissing = false)
|
||||
public class UsernamePasswordFiterLoginConfig implements LoginConfig {
|
||||
|
||||
private static final String API_LOGIN = "/api/login";
|
||||
|
||||
@Autowired
|
||||
private JwtTokenHelper jwtTokenHelper;
|
||||
|
||||
public GenericFilterBean authenticationProcessingFilter(AuthenticationManager authenticationManager) throws Exception {
|
||||
JwtAuthenticationFilter authenticationProcessingFilter = new JwtAuthenticationFilter(authenticationManager, jwtTokenHelper);
|
||||
authenticationProcessingFilter.setRequiresAuthenticationRequestMatcher(new RegexRequestMatcher(API_LOGIN, HttpMethod.POST.name(), false));
|
||||
return authenticationProcessingFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSecurity configureLoginHandler(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
|
||||
return http.addFilterAfter(authenticationProcessingFilter(authenticationManager), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package it.fabioformosa.quartzmanager.configuration.properties;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "quartz-manager.accounts.in-memory")
|
||||
@Getter @Setter
|
||||
public class InMemoryAccountProperties {
|
||||
private boolean enabled;
|
||||
private List<User> users;
|
||||
|
||||
@Getter @Setter
|
||||
public static class User {
|
||||
private String name;
|
||||
private String password;
|
||||
private List<String> roles = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package it.fabioformosa.quartzmanager.configuration.properties;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "quartz-manager.security.jwt")
|
||||
@Getter @Setter
|
||||
public class JwtSecurityProperties {
|
||||
private boolean enabled;
|
||||
private String secret;
|
||||
private long expirationInSec;
|
||||
private String header;
|
||||
private String cookie;
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import it.fabioformosa.quartzmanager.security.TokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.model.UserTokenState;
|
||||
import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsService;
|
||||
|
||||
@@ -39,12 +39,12 @@ public class AuthenticationController {
|
||||
private CustomUserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
TokenHelper tokenHelper;
|
||||
JwtTokenHelper tokenHelper;
|
||||
|
||||
@Value("${jwt.expires_in_sec}")
|
||||
@Value("${quartz-manager.security.jwt.expiration-in-sec}")
|
||||
private int EXPIRES_IN_SEC;
|
||||
|
||||
@Value("${jwt.cookie}")
|
||||
@Value("${quartz-manager.security.jwt.cookie}")
|
||||
private String TOKEN_COOKIE;
|
||||
|
||||
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
package it.fabioformosa.quartzmanager.security;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import it.fabioformosa.quartzmanager.configuration.properties.JwtSecurityProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* JWT Temporary disabled
|
||||
*
|
||||
* @author Fabio.Formosa
|
||||
*
|
||||
@@ -24,25 +28,32 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TokenHelper {
|
||||
public class JwtTokenHelper {
|
||||
|
||||
private static String base64EncodeSecretKey(String secretKey) {
|
||||
return Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Value("${app.name}")
|
||||
private String APP_NAME;
|
||||
|
||||
@Value("${jwt.secret}")
|
||||
private String SECRET;
|
||||
|
||||
@Value("${jwt.expires_in_sec}")
|
||||
private int EXPIRES_IN_SEC;
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String AUTH_HEADER;
|
||||
|
||||
@Value("${jwt.cookie}")
|
||||
private String AUTH_COOKIE;
|
||||
// @Value("${jwt.secret}")
|
||||
// private String SECRET;
|
||||
//
|
||||
// @Value("${jwt.expires_in_sec}")
|
||||
// private int EXPIRES_IN_SEC;
|
||||
//
|
||||
// @Value("${jwt.header}")
|
||||
// private String AUTH_HEADER;
|
||||
|
||||
// @Autowired
|
||||
// UserDetailsService userDetailsService;
|
||||
//
|
||||
// @Value("${jwt.cookie}")
|
||||
// private String AUTH_COOKIE;
|
||||
|
||||
@Autowired
|
||||
private JwtSecurityProperties jwtSecurityProps;
|
||||
|
||||
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
|
||||
|
||||
@@ -62,14 +73,14 @@ public class TokenHelper {
|
||||
}
|
||||
|
||||
private Date generateExpirationDate() {
|
||||
return new Date(getCurrentTimeMillis() + EXPIRES_IN_SEC * 1000);
|
||||
return new Date(getCurrentTimeMillis() + jwtSecurityProps.getExpirationInSec() * 1000);
|
||||
}
|
||||
|
||||
String generateToken(Map<String, Object> claims) {
|
||||
private String generateToken(Map<String, Object> claims) {
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setExpiration(generateExpirationDate())
|
||||
.signWith( SIGNATURE_ALGORITHM, SECRET )
|
||||
.signWith( SIGNATURE_ALGORITHM, base64EncodeSecretKey(jwtSecurityProps.getSecret()))
|
||||
.compact();
|
||||
}
|
||||
|
||||
@@ -79,7 +90,7 @@ public class TokenHelper {
|
||||
.setSubject(username)
|
||||
.setIssuedAt(generateCurrentDate())
|
||||
.setExpiration(generateExpirationDate())
|
||||
.signWith(SIGNATURE_ALGORITHM, SECRET)
|
||||
.signWith(SIGNATURE_ALGORITHM, base64EncodeSecretKey(jwtSecurityProps.getSecret()))
|
||||
.compact();
|
||||
}
|
||||
|
||||
@@ -87,7 +98,7 @@ public class TokenHelper {
|
||||
Claims claims;
|
||||
try {
|
||||
claims = Jwts.parser()
|
||||
.setSigningKey(SECRET)
|
||||
.setSigningKey(base64EncodeSecretKey(jwtSecurityProps.getSecret()))
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
} catch (Exception e) {
|
||||
@@ -119,12 +130,12 @@ public class TokenHelper {
|
||||
return DateTime.now().getMillis();
|
||||
}
|
||||
|
||||
public String getToken( HttpServletRequest request ) {
|
||||
Cookie authCookie = getCookieValueByName( request, AUTH_COOKIE );
|
||||
public String getToken(HttpServletRequest request) {
|
||||
Cookie authCookie = getCookieValueByName(request, jwtSecurityProps.getCookie());
|
||||
if ( authCookie != null )
|
||||
return authCookie.getValue();
|
||||
|
||||
String authHeader = request.getHeader(AUTH_HEADER);
|
||||
String authHeader = request.getHeader(jwtSecurityProps.getHeader());
|
||||
if ( authHeader != null && authHeader.startsWith("Bearer "))
|
||||
return authHeader.substring(7);
|
||||
|
||||
@@ -155,4 +166,8 @@ public class TokenHelper {
|
||||
}
|
||||
return refreshedToken;
|
||||
}
|
||||
|
||||
public void setHeader(HttpServletResponse response, String token) {
|
||||
response.addHeader(jwtSecurityProps.getHeader(), "Bearer " + token);
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,19 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
|
||||
super.onAuthenticationFailure(request, response, exception);
|
||||
}
|
||||
super.onAuthenticationFailure(request, response, exception);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||
@@ -16,54 +17,52 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import it.fabioformosa.quartzmanager.security.TokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.model.UserTokenState;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "quartz-manager.security.login-model", name = "form-login-enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
|
||||
|
||||
@Value("${jwt.expires_in_sec}")
|
||||
private int EXPIRES_IN_SEC;
|
||||
@Value("${quartz-manager.security.jwt.expiration-in-sec}")
|
||||
private int EXPIRES_IN_SEC;
|
||||
|
||||
@Value("${jwt.cookie}")
|
||||
private String TOKEN_COOKIE;
|
||||
@Value("${quartz-manager.security.jwt.cookie}")
|
||||
private String TOKEN_COOKIE;
|
||||
|
||||
@Autowired
|
||||
TokenHelper tokenHelper;
|
||||
//
|
||||
@Autowired
|
||||
ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
JwtTokenHelper tokenHelper;
|
||||
//
|
||||
@Autowired
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication ) throws IOException, ServletException {
|
||||
clearAuthenticationAttributes(request);
|
||||
User user = (User)authentication.getPrincipal();
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication ) throws IOException, ServletException {
|
||||
clearAuthenticationAttributes(request);
|
||||
User user = (User) authentication.getPrincipal();
|
||||
|
||||
String jws = tokenHelper.generateToken( user.getUsername() );
|
||||
String jws = tokenHelper.generateToken(user.getUsername());
|
||||
|
||||
Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
|
||||
Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
|
||||
authCookie.setHttpOnly(true);
|
||||
authCookie.setMaxAge(EXPIRES_IN_SEC);
|
||||
authCookie.setPath( "/quartz-manager" );
|
||||
response.addCookie(authCookie);
|
||||
|
||||
authCookie.setHttpOnly( true );
|
||||
// JWT is also in the response
|
||||
UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN_SEC);
|
||||
String jwtResponse = objectMapper.writeValueAsString( userTokenState );
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write( jwtResponse );
|
||||
|
||||
authCookie.setMaxAge( EXPIRES_IN_SEC );
|
||||
}
|
||||
|
||||
authCookie.setPath( "/quartz-manager" );
|
||||
response.addCookie( authCookie );
|
||||
|
||||
// JWT is also in the response
|
||||
UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN_SEC);
|
||||
String jwtResponse = objectMapper.writeValueAsString( userTokenState );
|
||||
response.setContentType("application/json");
|
||||
response.getWriter().write( jwtResponse );
|
||||
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
// Authentication authentication ) throws IOException, ServletException {
|
||||
// // clearAuthenticationAttributes(request);
|
||||
// response.setContentType("application/json");
|
||||
// response.getWriter().write( objectMapper.writeValueAsString("OK"));
|
||||
// }
|
||||
// @Override
|
||||
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
// Authentication authentication ) throws IOException, ServletException {
|
||||
// // clearAuthenticationAttributes(request);
|
||||
// response.setContentType("application/json");
|
||||
// response.getWriter().write( objectMapper.writeValueAsString("OK"));
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package it.fabioformosa.quartzmanager.security.auth;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
|
||||
|
||||
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
private final JwtTokenHelper jwtTokenHelper;
|
||||
|
||||
public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtTokenHelper jwtTokenHelper) {
|
||||
this.jwtTokenHelper = jwtTokenHelper;
|
||||
setAuthenticationManager(authenticationManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest req,
|
||||
HttpServletResponse res,
|
||||
FilterChain chain,
|
||||
Authentication auth) {
|
||||
UserDetails user = (UserDetails) auth.getPrincipal();
|
||||
String token = jwtTokenHelper.generateToken(user.getUsername());
|
||||
jwtTokenHelper.setHeader(res, token);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import it.fabioformosa.quartzmanager.security.TokenHelper;
|
||||
import it.fabioformosa.quartzmanager.security.JwtTokenHelper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@@ -38,7 +38,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
// private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private TokenHelper tokenHelper;
|
||||
private JwtTokenHelper tokenHelper;
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@@ -19,12 +19,6 @@ job:
|
||||
frequency: 4000
|
||||
repeatCount: 19
|
||||
|
||||
jwt:
|
||||
header: Authorization
|
||||
expires_in_sec: 600 # 10 minutes
|
||||
secret: queenvictoria
|
||||
cookie: AUTH-TOKEN
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.springframework.web: WARN
|
||||
@@ -33,8 +27,22 @@ logging:
|
||||
it.fabioformosa: DEBUG
|
||||
|
||||
quartz-manager:
|
||||
security:
|
||||
login-model:
|
||||
form-login-enabled: true
|
||||
userpwd-filter-enabled : false
|
||||
jwt:
|
||||
enabled: true
|
||||
secret: "bibidibobidiboo"
|
||||
expiration-in-sec: 28800 # 8 hours
|
||||
header: "Authorization"
|
||||
cookie: AUTH-TOKEN
|
||||
jobClass: it.fabioformosa.quartzmanager.jobs.myjobs.SampleJob
|
||||
account:
|
||||
user: admin
|
||||
pwd: admin
|
||||
|
||||
accounts:
|
||||
in-memory:
|
||||
enabled: true
|
||||
users:
|
||||
- name: admin
|
||||
password: admin
|
||||
roles:
|
||||
- ADMIN
|
||||
Reference in New Issue
Block a user