Skip to content
Snippets Groups Projects
Commit 00e3b019 authored by Julian Horner's avatar Julian Horner
Browse files

Add config, filter and controller packages

parent e8690c2f
No related branches found
No related tags found
No related merge requests found
/* /*
* Copyright 2019 (C) by Julian Horner. * Copyright 2019 (C) by Julian Horner.
* All Rights Reserved. * All Rights Reserved.
*/ */
package de.rtuni.ms.apig; package de.rtuni.ms.apig.config;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
/** /**
* Configuration class for json web token. * Configuration class for json web token.
* *
* @author Julian * @author Julian
* *
*/ */
public class JwtConfig { public class JwtConfig {
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
@Value("${security.jwt.uri:/auth/**}") @Value("${security.jwt.uri:/auth/**}")
private String Uri; private String Uri;
@Value("${security.jwt.header:Authorization}") @Value("${security.jwt.header:Authorization}")
private String header; private String header;
@Value("${security.jwt.prefix:Bearer}") @Value("${security.jwt.prefix:Bearer}")
private String prefix; private String prefix;
@Value("${security.jwt.expiration:#{24*60*60}}") @Value("${security.jwt.expiration:#{24*60*60}}")
private int expiration; private int expiration;
@Value("${security.jwt.secret:JwtSecretKey}") @Value("${security.jwt.secret:JwtSecretKey}")
private String secret; private String secret;
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
/** /**
* Get the uri. * Get the uri.
* *
* @return The uri * @return The uri
*/ */
public String getUri() { return Uri; } public String getUri() { return Uri; }
/** /**
* Get the header. * Get the header.
* *
* @return The header * @return The header
*/ */
public String getHeader() { return header; } public String getHeader() { return header; }
/** /**
* Get the prefix. * Get the prefix.
* *
* @return The prefix * @return The prefix
*/ */
public String getPrefix() { return prefix; } public String getPrefix() { return prefix; }
/** /**
* Get the expiration. * Get the expiration.
* *
* @return The expiration * @return The expiration
*/ */
public int getExpiration() { return expiration; } public int getExpiration() { return expiration; }
/** /**
* Get the secret. * Get the secret.
* *
* @return The secret * @return The secret
*/ */
public String getSecret() { return secret; } public String getSecret() { return secret; }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
} }
/* /*
* Copyright 2019 (C) by Julian Horner. * Copyright 2019 (C) by Julian Horner.
* All Rights Reserved. * All Rights Reserved.
*/ */
package de.rtuni.ms.apig; package de.rtuni.ms.apig.config;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/** import de.rtuni.ms.apig.filter.JwtTokenAuthenticationFilter;
* Class that enables custom security configuration.
* /**
* @author Julian * Class that enables custom security configuration.
*/ *
@EnableWebSecurity * @author Julian
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { */
//---------------------------------------------------------------------------------------------- @EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
/** The <code>JwtConfig</code> for the json web token. */ //----------------------------------------------------------------------------------------------
@Autowired
private JwtConfig jwtConfig; /** The <code>JwtConfig</code> for the json web token. */
@Autowired
//---------------------------------------------------------------------------------------------- private JwtConfig jwtConfig;
/** //----------------------------------------------------------------------------------------------
* Overrides the default security configuration.
*/ /**
@Override * Overrides the default security configuration.
protected void configure(HttpSecurity http) throws Exception { */
http.csrf().disable() @Override
// make sure we use stateless session; session won't be used to store user's state. protected void configure(HttpSecurity http) throws Exception {
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() http.csrf().disable()
// make sure we use stateless session; session won't be used to store user's state.
// Add a filter to validate the tokens with every request. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig),
UsernamePasswordAuthenticationFilter.class) // Add a filter to validate the tokens with every request.
.addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfig),
.authorizeRequests() UsernamePasswordAuthenticationFilter.class)
.antMatchers("/auth/**").permitAll()
// Anyone who is trying to access the securedPage must be an ADMIN. .authorizeRequests()
// TODO can we change the path to /securedPage? .antMatchers("/auth/**").permitAll()
.antMatchers("/securedPage/**").hasRole("ADMIN") // Anyone who is trying to access the securedPage must be an ADMIN.
// Permit default path. // TODO can we change the path to /securedPage?
.antMatchers("/login").permitAll().and() .antMatchers("/securedPage/**").hasRole("ADMIN")
// Configures where to forward if authentication is required. // Permit default path.
.formLogin().loginPage("/login") .antMatchers("/login").permitAll().and()
// Configures url for processing of login data. // Configures where to forward if authentication is required.
.loginProcessingUrl("process_login") // TODO can we remove this? .formLogin().loginPage("/login")
// Configures where to go if there is no previous visited page. // Configures url for processing of login data.
.defaultSuccessUrl("/", true).and() .loginProcessingUrl("process_login") // TODO can we remove this?
// Configures url for processing of logout. // Configures where to go if there is no previous visited page.
.logout().logoutUrl("/process_logout") .defaultSuccessUrl("/", true).and()
.deleteCookies("JSESSIONID"); // TODO i think we can remove this // Configures url for processing of logout.
} .logout().logoutUrl("/process_logout")
.deleteCookies("JSESSIONID"); // TODO i think we can remove this
//---------------------------------------------------------------------------------------------- }
/** //----------------------------------------------------------------------------------------------
* Get a new <code>JwtConfig</code>.
* /**
* @return The stated configuration * Get a new <code>JwtConfig</code>.
*/ *
@Bean * @return The stated configuration
public JwtConfig jwtConfig() { */
return new JwtConfig(); @Bean
} public JwtConfig jwtConfig() {
return new JwtConfig();
//---------------------------------------------------------------------------------------------- }
}
//----------------------------------------------------------------------------------------------
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* All Rights Reserved. * All Rights Reserved.
*/ */
package de.rtuni.ms.apig; package de.rtuni.ms.apig.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
......
/* /*
* Copyright 2019 (C) by Julian Horner. * Copyright 2019 (C) by Julian Horner.
* All Rights Reserved. * All Rights Reserved.
*/ */
package de.rtuni.ms.apig; package de.rtuni.ms.apig.filter;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import io.jsonwebtoken.Claims; import de.rtuni.ms.apig.config.JwtConfig;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
/**
* Filter class for authentication of the provided JSON web token. /**
* * Filter class for authentication of the provided JSON web token.
* @author Julian *
*/ * @author Julian
public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { */
//---------------------------------------------------------------------------------------------- public class JwtTokenAuthenticationFilter extends OncePerRequestFilter {
//----------------------------------------------------------------------------------------------
/** The <code>JwtConfig</code> for the json web token. */
private final JwtConfig jwtConfig; /** The <code>JwtConfig</code> for the json web token. */
private final JwtConfig jwtConfig;
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/**
* Set the given <code>JwtConfig</code> for the token. /**
* * Set the given <code>JwtConfig</code> for the token.
* @param config The stated configuration *
*/ * @param config The stated configuration
public JwtTokenAuthenticationFilter(final JwtConfig config) { jwtConfig = config; } */
public JwtTokenAuthenticationFilter(final JwtConfig config) { jwtConfig = config; }
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/**
* If a token is supplied by the user the token will be decrypt and the user will be set as /**
* currently authenticated user. That includes the authorities which were granted to the * If a token is supplied by the user the token will be decrypt and the user will be set as
* user by the authentication service. If there is no supplied token the next filter will be * currently authenticated user. That includes the authorities which were granted to the
* executed. * user by the authentication service. If there is no supplied token the next filter will be
* <p> * executed.
* {@inheritDoc} * <p>
*/ * {@inheritDoc}
@Override */
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, @Override
FilterChain chain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
// Gets the authentication header.
String bearerToken = request.getParameter("access_token"); // Gets the authentication header.
// Validate the header and check the prefix. String bearerToken = request.getParameter("access_token");
if (bearerToken == null || !bearerToken.startsWith(jwtConfig.getPrefix())) { // Validate the header and check the prefix.
// If no token is provided the user is not authenticated if (bearerToken == null || !bearerToken.startsWith(jwtConfig.getPrefix())) {
// and we continue with the next filter. // If no token is provided the user is not authenticated
// Thats okay because maybe the user is accessing a public path. // and we continue with the next filter.
chain.doFilter(request, response); // If not valid, go to the next filter. // Thats okay because maybe the user is accessing a public path.
chain.doFilter(request, response); // If not valid, go to the next filter.
return;
} return;
}
// Removes the bearer substring from the authentication header.
String token = bearerToken.replace(jwtConfig.getPrefix(), ""); // Removes the bearer substring from the authentication header.
String token = bearerToken.replace(jwtConfig.getPrefix(), "");
// Note that exceptions can be triggered when creating claims, e.g if the token has expired.
try { // Note that exceptions can be triggered when creating claims, e.g if the token has expired.
// Sets secret and decrypt the token. try {
Claims claims = Jwts.parser().setSigningKey(jwtConfig.getSecret().getBytes()) // Sets secret and decrypt the token.
.parseClaimsJws(token).getBody(); Claims claims = Jwts.parser().setSigningKey(jwtConfig.getSecret().getBytes())
.parseClaimsJws(token).getBody();
String username = claims.getSubject();
if (username != null) { String username = claims.getSubject();
// Gets the authorities which were added to the token by the auth-service. if (username != null) {
@SuppressWarnings("unchecked") // Gets the authorities which were added to the token by the auth-service.
List<String> authorities = (List<String>) claims.get("authorities"); @SuppressWarnings("unchecked")
List<String> authorities = (List<String>) claims.get("authorities");
// Create an UsernamePasswordAuthenticationToken which represents the
// authenticated user or the user who is being authenticated currently. // Create an UsernamePasswordAuthenticationToken which represents the
// // authenticated user or the user who is being authenticated currently.
// Because we need a list of authorities, which are from the type GrantedAuthority //
// we have to convert the Strings to SimpleGrantedAuthority which is an // Because we need a list of authorities, which are from the type GrantedAuthority
// implementation. // we have to convert the Strings to SimpleGrantedAuthority which is an
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken( // implementation.
username, null, authorities.stream() UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
.map(SimpleGrantedAuthority::new).collect(Collectors.toList())); username, null, authorities.stream()
.map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
// Set the user as new authenticated user.
SecurityContextHolder.getContext().setAuthentication(auth); // Set the user as new authenticated user.
} SecurityContextHolder.getContext().setAuthentication(auth);
} catch (Exception e) { }
// In case of failure. Make sure user won't be authenticated. } catch (Exception e) {
SecurityContextHolder.clearContext(); // In case of failure. Make sure user won't be authenticated.
} SecurityContextHolder.clearContext();
}
chain.doFilter(request, response);
} chain.doFilter(request, response);
}
//----------------------------------------------------------------------------------------------
} //----------------------------------------------------------------------------------------------
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment