Enabled JWT Security Config

This commit is contained in:
fabio.formosa
2019-07-03 00:30:03 +02:00
parent 3334d36105
commit 8440a431d0
23 changed files with 524 additions and 497 deletions

View File

@@ -4,13 +4,10 @@ import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -20,12 +17,12 @@ import it.fabioformosa.quartzmanager.security.ComboEntryPoint;
import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler;
import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
//@Configuration
//@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Configuration
// @Configuration
@Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@@ -45,7 +42,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
}
@Configuration
// @Configuration
@Order(2)
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter {

View File

@@ -1,16 +1,18 @@
package it.fabioformosa.quartzmanager.configuration;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@@ -18,88 +20,109 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import it.fabioformosa.quartzmanager.security.ComboEntryPoint;
import it.fabioformosa.quartzmanager.security.auth.AuthenticationFailureHandler;
import it.fabioformosa.quartzmanager.security.auth.AuthenticationSuccessHandler;
import it.fabioformosa.quartzmanager.security.auth.LogoutSuccess;
import it.fabioformosa.quartzmanager.security.auth.RestAuthenticationEntryPoint;
import it.fabioformosa.quartzmanager.security.auth.TokenAuthenticationFilter;
import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsService;
/**
* JWT Temporary disabled
*
*
* @author Fabio.Formosa
*
*/
//@Configuration
//@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter {
@Value("${jwt.cookie}")
private String TOKEN_COOKIE;
@Value("${jwt.cookie}")
private String TOKEN_COOKIE;
@Autowired
private CustomUserDetailsService jwtUserDetailsService;
// @Autowired
// private CustomUserDetailsService jwtUserDetailsService;
// @Autowired
// private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Resource
private ComboEntryPoint comboEntryPoint;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private LogoutSuccess logoutSuccess;
@Autowired
private LogoutSuccess logoutSuccess;
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Value("${quartz-manager.account.user}")
private String adminUser;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {
authenticationManagerBuilder.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoder());
@Value("${quartz-manager.account.pwd}")
private String adminPwd;
}
// @Bean
// @Override
// public AuthenticationManager authenticationManagerBean() throws Exception {
// return super.authenticationManagerBean();
// }
@Bean
public TokenAuthenticationFilter jwtAuthenticationTokenFilter() throws Exception {
return new TokenAuthenticationFilter();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", //
"/js/**", //
"/img/**", //
"/lib/**", //
"/swagger-resources/**", "/swagger-ui.html","/v2/api-docs", //
"/webjars/**");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@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");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().ignoringAntMatchers("/api/login", "/api/signup")
// .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
http.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.exceptionHandling().authenticationEntryPoint(comboEntryPoint).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
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
// @Bean
// public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// }
@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
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}

View File

@@ -21,7 +21,7 @@ import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsServ
/**
* JWT Temporary disabled
*
*
* @author Fabio.Formosa
*
*/
@@ -30,53 +30,53 @@ import it.fabioformosa.quartzmanager.security.service.impl.CustomUserDetailsServ
//@RequestMapping( value = "/api", produces = MediaType.APPLICATION_JSON_VALUE )
public class AuthenticationController {
static class PasswordChanger {
public String oldPassword;
public String newPassword;
}
static class PasswordChanger {
public String oldPassword;
public String newPassword;
}
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
TokenHelper tokenHelper;
@Autowired
TokenHelper tokenHelper;
@Value("${jwt.expires_in}")
private int EXPIRES_IN;
@Value("${jwt.expires_in_sec}")
private int EXPIRES_IN_SEC;
@Value("${jwt.cookie}")
private String TOKEN_COOKIE;
@Value("${jwt.cookie}")
private String TOKEN_COOKIE;
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
@PreAuthorize("hasRole('USER')")
public ResponseEntity<?> changePassword(@RequestBody PasswordChanger passwordChanger) {
userDetailsService.changePassword(passwordChanger.oldPassword, passwordChanger.newPassword);
Map<String, String> result = new HashMap<>();
result.put( "result", "success" );
return ResponseEntity.accepted().body(result);
}
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
@PreAuthorize("hasRole('USER')")
public ResponseEntity<?> changePassword(@RequestBody PasswordChanger passwordChanger) {
userDetailsService.changePassword(passwordChanger.oldPassword, passwordChanger.newPassword);
Map<String, String> result = new HashMap<>();
result.put( "result", "success" );
return ResponseEntity.accepted().body(result);
}
@RequestMapping(value = "/refresh", method = RequestMethod.GET)
public ResponseEntity<?> refreshAuthenticationToken(HttpServletRequest request, HttpServletResponse response) {
@RequestMapping(value = "/refresh", method = RequestMethod.GET)
public ResponseEntity<?> refreshAuthenticationToken(HttpServletRequest request, HttpServletResponse response) {
String authToken = tokenHelper.getToken( request );
if (authToken != null && tokenHelper.canTokenBeRefreshed(authToken)) {
// TODO check user password last update
String refreshedToken = tokenHelper.refreshToken(authToken);
String authToken = tokenHelper.getToken( request );
if (authToken != null && tokenHelper.canTokenBeRefreshed(authToken)) {
// TODO check user password last update
String refreshedToken = tokenHelper.refreshToken(authToken);
Cookie authCookie = new Cookie( TOKEN_COOKIE, refreshedToken );
authCookie.setPath( "/" );
authCookie.setHttpOnly( true );
authCookie.setMaxAge( EXPIRES_IN );
// Add cookie to response
response.addCookie( authCookie );
Cookie authCookie = new Cookie( TOKEN_COOKIE, refreshedToken );
authCookie.setPath( "/quartz-manager" );
authCookie.setHttpOnly( true );
authCookie.setMaxAge( EXPIRES_IN_SEC );
// Add cookie to response
response.addCookie( authCookie );
UserTokenState userTokenState = new UserTokenState(refreshedToken, EXPIRES_IN);
return ResponseEntity.ok(userTokenState);
} else {
UserTokenState userTokenState = new UserTokenState();
return ResponseEntity.accepted().body(userTokenState);
}
}
UserTokenState userTokenState = new UserTokenState(refreshedToken, EXPIRES_IN_SEC);
return ResponseEntity.ok(userTokenState);
} else {
UserTokenState userTokenState = new UserTokenState();
return ResponseEntity.accepted().body(userTokenState);
}
}
}

View File

@@ -7,155 +7,152 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
/**
* JWT Temporary disabled
*
*
* @author Fabio.Formosa
*
*/
//@Component
@Slf4j
@Component
public class TokenHelper {
@Value("${app.name}")
private String APP_NAME;
@Value("${app.name}")
private String APP_NAME;
@Value("${jwt.secret}")
private String SECRET;
@Value("${jwt.secret}")
private String SECRET;
@Value("${jwt.expires_in}")
private int EXPIRES_IN;
@Value("${jwt.expires_in_sec}")
private int EXPIRES_IN_SEC;
@Value("${jwt.header}")
private String AUTH_HEADER;
@Value("${jwt.header}")
private String AUTH_HEADER;
@Value("${jwt.cookie}")
private String AUTH_COOKIE;
@Value("${jwt.cookie}")
private String AUTH_COOKIE;
@Autowired
UserDetailsService userDetailsService;
// @Autowired
// UserDetailsService userDetailsService;
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
public Boolean canTokenBeRefreshed(String token) {
try {
final Date expirationDate = getClaimsFromToken(token).getExpiration();
// String username = getUsernameFromToken(token);
// UserDetails userDetails = userDetailsService.loadUserByUsername(username);
return expirationDate.compareTo(generateCurrentDate()) > 0;
} catch (Exception e) {
return false;
}
}
public Boolean canTokenBeRefreshed(String token) {
try {
final Date expirationDate = getClaimsFromToken(token).getExpiration();
// String username = getUsernameFromToken(token);
// UserDetails userDetails = userDetailsService.loadUserByUsername(username);
return expirationDate.compareTo(generateCurrentDate()) > 0;
} catch (Exception e) {
return false;
}
}
public String generateToken(String username) {
return Jwts.builder()
.setIssuer( APP_NAME )
.setSubject(username)
.setIssuedAt(generateCurrentDate())
.setExpiration(generateExpirationDate())
.signWith( SIGNATURE_ALGORITHM, SECRET )
.compact();
}
public String generateToken(String username) {
return Jwts.builder()
.setIssuer(APP_NAME)
.setSubject(username)
.setIssuedAt(generateCurrentDate())
.setExpiration(generateExpirationDate())
.signWith(SIGNATURE_ALGORITHM, SECRET)
.compact();
}
/**
* Find a specific HTTP cookie in a request.
*
* @param request
* The HTTP request object.
* @param name
* The cookie name to look for.
* @return The cookie, or <code>null</code> if not found.
*/
public Cookie getCookieValueByName(HttpServletRequest request, String name) {
if (request.getCookies() == null)
return null;
for (int i = 0; i < request.getCookies().length; i++)
if (request.getCookies()[i].getName().equals(name))
return request.getCookies()[i];
return null;
}
/**
* Find a specific HTTP cookie in a request.
*
* @param request
* The HTTP request object.
* @param name
* The cookie name to look for.
* @return The cookie, or <code>null</code> if not found.
*/
public Cookie getCookieValueByName(HttpServletRequest request, String name) {
if (request.getCookies() == null)
return null;
for (int i = 0; i < request.getCookies().length; i++)
if (request.getCookies()[i].getName().equals(name))
return request.getCookies()[i];
return null;
}
public String getToken( HttpServletRequest request ) {
/**
* Getting the token from Cookie store
*/
Cookie authCookie = getCookieValueByName( request, AUTH_COOKIE );
if ( authCookie != null )
return authCookie.getValue();
/**
* Getting the token from Authentication header
* e.g Bearer your_token
*/
String authHeader = request.getHeader(AUTH_HEADER);
if ( authHeader != null && authHeader.startsWith("Bearer "))
return authHeader.substring(7);
public String getToken( HttpServletRequest request ) {
Cookie authCookie = getCookieValueByName( request, AUTH_COOKIE );
if ( authCookie != null )
return authCookie.getValue();
return null;
}
String authHeader = request.getHeader(AUTH_HEADER);
if ( authHeader != null && authHeader.startsWith("Bearer "))
return authHeader.substring(7);
public String getUsernameFromToken(String token) {
String username;
try {
final Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
return null;
}
public String refreshToken(String token) {
String refreshedToken;
try {
final Claims claims = getClaimsFromToken(token);
claims.setIssuedAt(generateCurrentDate());
refreshedToken = generateToken(claims);
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}
public String getUsernameFromToken(String token) {
String username;
try {
final Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
log.error("Error getting claims from jwt token due to " + e.getMessage(), e);
}
return username;
}
private Date generateCurrentDate() {
return new Date(getCurrentTimeMillis());
}
public String refreshToken(String token) {
String refreshedToken;
try {
final Claims claims = getClaimsFromToken(token);
claims.setIssuedAt(generateCurrentDate());
refreshedToken = generateToken(claims);
} catch (Exception e) {
log.error("Error refreshing jwt token due to " + e.getMessage(), e);
refreshedToken = null;
}
return refreshedToken;
}
private Date generateExpirationDate() {
private Date generateCurrentDate() {
return new Date(getCurrentTimeMillis());
}
return new Date(getCurrentTimeMillis() + EXPIRES_IN * 1000);
}
private Date generateExpirationDate() {
return new Date(getCurrentTimeMillis() + EXPIRES_IN_SEC * 1000);
}
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
log.error("Error getting claims from jwt token due to " + e.getMessage(), e);
}
return claims;
}
private long getCurrentTimeMillis() {
return DateTime.now().getMillis();
}
private long getCurrentTimeMillis() {
return DateTime.now().getMillis();
}
String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith( SIGNATURE_ALGORITHM, SECRET )
.compact();
}
String generateToken(Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith( SIGNATURE_ALGORITHM, SECRET )
.compact();
}
}

View File

@@ -3,6 +3,7 @@ package it.fabioformosa.quartzmanager.security.auth;
import org.springframework.security.authentication.AbstractAuthenticationToken;
public class AnonAuthentication extends AbstractAuthenticationToken {
private static final long serialVersionUID = 1L;
public AnonAuthentication() {
super( null );

View File

@@ -3,63 +3,67 @@ package it.fabioformosa.quartzmanager.security.auth;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.fabioformosa.quartzmanager.security.TokenHelper;
import it.fabioformosa.quartzmanager.security.model.UserTokenState;
@Component
public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
// @Value("${jwt.expires_in}")
// private int EXPIRES_IN;
//
// @Value("${jwt.cookie}")
// private String TOKEN_COOKIE;
//
// @Autowired
// TokenHelper tokenHelper;
@Value("${jwt.expires_in_sec}")
private int EXPIRES_IN_SEC;
@Value("${jwt.cookie}")
private String TOKEN_COOKIE;
@Autowired
TokenHelper tokenHelper;
//
@Autowired
ObjectMapper objectMapper;
//
// @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() );
//
// // Create token auth Cookie
// Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
//
// authCookie.setHttpOnly( true );
//
// authCookie.setMaxAge( EXPIRES_IN );
//
// authCookie.setPath( "/" );
// // Add cookie to response
// response.addCookie( authCookie );
//
// // JWT is also in the response
// UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN);
// 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);
clearAuthenticationAttributes(request);
User user = (User)authentication.getPrincipal();
String jws = tokenHelper.generateToken( user.getUsername() );
Cookie authCookie = new Cookie( TOKEN_COOKIE, jws );
authCookie.setHttpOnly( true );
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( objectMapper.writeValueAsString("OK"));
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"));
// }
}

View File

@@ -17,8 +17,6 @@ public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
// This is invoked when user tries to access a secured REST resource without supplying any credentials
// We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}

View File

@@ -10,8 +10,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
@@ -23,28 +21,27 @@ import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import it.fabioformosa.quartzmanager.security.TokenHelper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {
/*
* The below paths will get ignored by the filter
*/
public static final String ROOT_MATCHER = "/";
public static final String FAVICON_MATCHER = "/favicon.ico";
public static final String HTML_MATCHER = "/**/*.html";
public static final String CSS_MATCHER = "/**/*.css";
public static final String JS_MATCHER = "/**/*.js";
public static final String IMG_MATCHER = "/images/*";
public static final String LOGIN_MATCHER = "/auth/login";
public static final String LOGOUT_MATCHER = "/auth/logout";
private final Log logger = LogFactory.getLog(this.getClass());
// private final Log logger = LogFactory.getLog(this.getClass());
@Autowired
TokenHelper tokenHelper;
private TokenHelper tokenHelper;
@Autowired
UserDetailsService userDetailsService;
private UserDetailsService userDetailsService;
private List<String> pathsToSkip = Arrays.asList(
ROOT_MATCHER,
@@ -60,13 +57,10 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String authToken = tokenHelper.getToken(request);
if (authToken != null && !skipPathRequest(request, pathsToSkip))
// get username from token
try {
String username = tokenHelper.getUsernameFromToken(authToken);
// get user
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// create authentication
TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
@@ -74,6 +68,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication());
log.error("Switched to Anonimous Authentication, "
+ "because an error occurred setting authentication in security context holder due to " + e.getMessage(), e);
}
else
SecurityContextHolder.getContext().setAuthentication(new AnonAuthentication());

View File

@@ -6,6 +6,8 @@ import org.springframework.security.core.userdetails.UserDetails;
public class TokenBasedAuthentication extends AbstractAuthenticationToken {
private static final long serialVersionUID = 1L;
private String token;
private final UserDetails principle;

View File

@@ -1,11 +1,9 @@
package it.fabioformosa.quartzmanager.security.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
@@ -13,43 +11,43 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* Temporary enabled only inMemoryAuthentication
*
*
* @author Fabio.Formosa
*
*/
@Entity
@Table(name="Authority")
//@Entity
//@Table(name="Authority")
public class Authority implements GrantedAuthority {
@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name="name")
String name;
@Column(name="name")
String name;
@Override
public String getAuthority() {
return name;
}
@Override
public String getAuthority() {
return name;
}
@JsonIgnore
public Long getId() {
return id;
}
@JsonIgnore
public Long getId() {
return id;
}
@JsonIgnore
public String getName() {
return name;
}
@JsonIgnore
public String getName() {
return name;
}
public void setId(Long id) {
this.id = id;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -6,7 +6,6 @@ import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@@ -14,7 +13,6 @@ import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -23,113 +21,113 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* Temporary enabled only inMemoryAuthentication
*
*
* @author Fabio.Formosa
*
*/
@Entity
@Table(name = "USER")
//@Entity
//@Table(name = "USER")
public class User implements UserDetails, Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
@Column(name = "username")
private String username;
@JsonIgnore
@Column(name = "password")
private String password;
@JsonIgnore
@Column(name = "password")
private String password;
@Column(name = "firstname")
private String firstname;
@Column(name = "firstname")
private String firstname;
@Column(name = "lastname")
private String lastname;
@Column(name = "lastname")
private String lastname;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_authority",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id"))
private List<Authority> authorities;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_authority",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id"))
private List<Authority> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public String getFirstname() {
return firstname;
}
public String getFirstname() {
return firstname;
}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public String getLastname() {
return lastname;
}
public String getLastname() {
return lastname;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getUsername() {
return username;
}
// We can add the below fields in the users table.
// For now, they are hardcoded.
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
// We can add the below fields in the users table.
// For now, they are hardcoded.
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public void setId(Long id) {
this.id = id;
}
public void setId(Long id) {
this.id = id;
}
public void setLastname(String lastname) {
public void setLastname(String lastname) {
this.lastname = lastname;
}
this.lastname = lastname;
}
public void setPassword(String password) {
this.password = password;
}
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@@ -2,31 +2,31 @@ package it.fabioformosa.quartzmanager.security.model;
public class UserTokenState {
private String access_token;
private Long expires_in;
private Long expires_in_sec;
public UserTokenState() {
this.access_token = null;
this.expires_in = null;
this.expires_in_sec = null;
}
public UserTokenState(String access_token, long expires_in) {
public UserTokenState(String access_token, long expires_in_sec) {
this.access_token = access_token;
this.expires_in = expires_in;
this.expires_in_sec = expires_in_sec;
}
public String getAccess_token() {
return access_token;
}
public Long getExpires_in() {
return expires_in;
public Long getExpires_in_sec() {
return expires_in_sec;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
public void setExpires_in_sec(Long expires_in_sec) {
this.expires_in_sec = expires_in_sec;
}
}

View File

@@ -1,9 +1,13 @@
package it.fabioformosa.quartzmanager.security.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import it.fabioformosa.quartzmanager.security.model.Authority;
public interface AuthorityRepository extends JpaRepository<Authority, Long> {
Authority findByName(String name);
/**
* Temporary disabled
*
* @author Fabio
*
*/
//public interface AuthorityRepository extends JpaRepository<Authority, Long> {
// Authority findByName(String name);
//}
public interface AuthorityRepository {
}

View File

@@ -1,10 +1,11 @@
package it.fabioformosa.quartzmanager.security.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import it.fabioformosa.quartzmanager.security.model.User;
public interface UserRepository extends JpaRepository<User, Long> {
public interface UserRepository {
User findByUsername( String username );
}
//public interface UserRepository extends JpaRepository<User, Long> {
// User findByUsername( String username );
//}

View File

@@ -1,12 +1,13 @@
package it.fabioformosa.quartzmanager.security.service;
import java.util.List;
import it.fabioformosa.quartzmanager.security.model.Authority;
/**
* temporary disabled
* @author Fabio
*
*/
public interface AuthorityService {
List<Authority> findById(Long id);
List<Authority> findByname(String name);
// List<Authority> findById(Long id);
//
// List<Authority> findByname(String name);
}

View File

@@ -1,34 +1,33 @@
package it.fabioformosa.quartzmanager.security.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import it.fabioformosa.quartzmanager.security.model.Authority;
import it.fabioformosa.quartzmanager.security.repository.AuthorityRepository;
import it.fabioformosa.quartzmanager.security.service.AuthorityService;
/**
* Temporary disabled
* @author Fabio
*
*/
//@Service
public class AuthorityServiceImpl implements AuthorityService {
@Autowired
private AuthorityRepository authorityRepository;
@Override
public List<Authority> findById(Long id) {
Authority auth = this.authorityRepository.getOne(id);
List<Authority> auths = new ArrayList<>();
auths.add(auth);
return auths;
}
@Override
public List<Authority> findByname(String name) {
Authority auth = this.authorityRepository.findByName(name);
List<Authority> auths = new ArrayList<>();
auths.add(auth);
return auths;
}
// @Autowired
// private AuthorityRepository authorityRepository;
//
// @Override
// public List<Authority> findById(Long id) {
// Authority auth = this.authorityRepository.getOne(id);
// List<Authority> auths = new ArrayList<>();
// auths.add(auth);
// return auths;
// }
//
// @Override
// public List<Authority> findByname(String name) {
// Authority auth = this.authorityRepository.findByName(name);
// List<Authority> auths = new ArrayList<>();
// auths.add(auth);
// return auths;
// }
}

View File

@@ -4,9 +4,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -15,7 +12,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import it.fabioformosa.quartzmanager.security.model.User;
import it.fabioformosa.quartzmanager.security.repository.UserRepository;
/**
* Temporary disabled
* @author Fabio
*
*/
//@Service
public class CustomUserDetailsService implements UserDetailsService {
@@ -32,25 +33,25 @@ public class CustomUserDetailsService implements UserDetailsService {
public void changePassword(String oldPassword, String newPassword) {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
String username = currentUser.getName();
if (authenticationManager != null) {
LOGGER.debug("Re-authenticating user '"+ username + "' for password change request.");
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword));
} else {
LOGGER.debug("No authentication manager set. can't change Password!");
return;
}
LOGGER.debug("Changing password for user '"+ username + "'");
User user = (User) loadUserByUsername(username);
user.setPassword(passwordEncoder.encode(newPassword));
userRepository.save(user);
// Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
// String username = currentUser.getName();
//
// if (authenticationManager != null) {
// LOGGER.debug("Re-authenticating user '"+ username + "' for password change request.");
//
// authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword));
// } else {
// LOGGER.debug("No authentication manager set. can't change Password!");
//
// return;
// }
//
// LOGGER.debug("Changing password for user '"+ username + "'");
//
// User user = (User) loadUserByUsername(username);
//
// user.setPassword(passwordEncoder.encode(newPassword));
// userRepository.save(user);
}

View File

@@ -8,13 +8,17 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import it.fabioformosa.quartzmanager.security.model.Authority;
import it.fabioformosa.quartzmanager.security.model.User;
import it.fabioformosa.quartzmanager.security.model.UserRequest;
import it.fabioformosa.quartzmanager.security.repository.UserRepository;
import it.fabioformosa.quartzmanager.security.service.AuthorityService;
import it.fabioformosa.quartzmanager.security.service.UserService;
/**
* Temporary disabled
* @author Fabio
*
*/
//@Service
public class UserServiceImpl implements UserService {
@@ -30,15 +34,17 @@ public class UserServiceImpl implements UserService {
@Override
@PreAuthorize("hasRole('ADMIN')")
public List<User> findAll() throws AccessDeniedException {
List<User> result = userRepository.findAll();
return result;
// List<User> result = userRepository.findAll();
// return result;
return null;
}
@Override
@PreAuthorize("hasRole('ADMIN')")
public User findById(Long id) throws AccessDeniedException {
User u = userRepository.getOne(id);
return u;
// User u = userRepository.getOne(id);
// return u;
return null;
}
@Override
@@ -50,23 +56,23 @@ public class UserServiceImpl implements UserService {
@Override
public void resetCredentials() {
List<User> users = userRepository.findAll();
for (User user : users) {
user.setPassword(passwordEncoder.encode("123"));
userRepository.save(user);
}
// List<User> users = userRepository.findAll();
// for (User user : users) {
// user.setPassword(passwordEncoder.encode("123"));
// userRepository.save(user);
// }
}
@Override
public User save(UserRequest userRequest) {
User user = new User();
user.setUsername(userRequest.getUsername());
user.setPassword(passwordEncoder.encode(userRequest.getPassword()));
user.setFirstname(userRequest.getFirstname());
user.setLastname(userRequest.getLastname());
List<Authority> auth = authService.findByname("ROLE_USER");
user.setAuthorities(auth);
this.userRepository.save(user);
// user.setUsername(userRequest.getUsername());
// user.setPassword(passwordEncoder.encode(userRequest.getPassword()));
// user.setFirstname(userRequest.getFirstname());
// user.setLastname(userRequest.getLastname());
// List<Authority> auth = authService.findByname("ROLE_USER");
// user.setAuthorities(auth);
// this.userRepository.save(user);
return user;
}

View File

@@ -21,14 +21,16 @@ job:
jwt:
header: Authorization
expires_in: 600 # 10 minutes
expires_in_sec: 600 # 10 minutes
secret: queenvictoria
cookie: AUTH-TOKEN
logging:
level:
org.springframework.web: WARN
it.fabioformosa: INFO
org.springframework.security: INFO
org.springframework.boot.autoconfigure.security: INFO
it.fabioformosa: DEBUG
quartz-manager:
jobClass: it.fabioformosa.quartzmanager.jobs.myjobs.SampleJob

View File

@@ -24,7 +24,7 @@ export class SchedulerConfigComponent implements OnInit {
this.schedulerService.getConfig()
.subscribe(res => {
this.config = new SchedulerConfig(res.triggerPerDay, res.maxCount)
this.configBackup = res.maxCount
this.configBackup = res
})
}

View File

@@ -9,13 +9,12 @@ export class AdminGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (this.userService.currentUser) {
if (JSON.stringify(this.userService.currentUser.authorities).search('ROLE_ADMIN') !== -1) {
if (JSON.stringify(this.userService.currentUser.authorities).search('ROLE_ADMIN') !== -1)
return true;
} else {
else {
this.router.navigate(['/403']);
return false;
}
} else {
console.log('NOT AN ADMIN ROLE');
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});

View File

@@ -43,15 +43,15 @@ export class LoginComponent implements OnInit, OnDestroy {
ngOnInit() {
this.route.params
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((params: DisplayMessage) => {
this.notification = params;
});
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
this.form = this.formBuilder.group({
username: ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(64)])],
password: ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(32)])]
});
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((params: DisplayMessage) => {
this.notification = params;
});
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
this.form = this.formBuilder.group({
username: ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(64)])],
password: ['', Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(48)])]
});
}
ngOnDestroy() {