Browse Source

Adding repository and security classes

main
ddangelorb 3 years ago
parent
commit
a746e85132
  1. 16
      src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java
  2. 40
      src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenFilter.java
  3. 22
      src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenFilterConfigurer.java
  4. 91
      src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenProvider.java
  5. 35
      src/main/java/org/waterproofingdata/wpdauth/security/MyUserDetails.java
  6. 78
      src/main/java/org/waterproofingdata/wpdauth/security/WebSecurityConfig.java

16
src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java

@ -0,0 +1,16 @@
package org.waterproofingdata.wpdauth.repository;
import org.waterproofingdata.wpdauth.model.Users;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UsersRepository extends JpaRepository<Users, Integer> {
boolean existsByUsername(String username);
Users findByUsername(String username);
//@Transactional
//void activateByUsername(String username);
}

40
src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenFilter.java

@ -0,0 +1,40 @@
package org.waterproofingdata.wpdauth.security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.waterproofingdata.wpdauth.security.JwtTokenProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.waterproofingdata.wpdauth.exception.CustomException;
import org.springframework.web.filter.OncePerRequestFilter;
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(httpServletRequest);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (CustomException ex) {
//this is very important, since it guarantees the user is not authenticated at all
SecurityContextHolder.clearContext();
httpServletResponse.sendError(ex.getHttpStatus().value(), ex.getMessage());
return;
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}

22
src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenFilterConfigurer.java

@ -0,0 +1,22 @@
package org.waterproofingdata.wpdauth.security;
import org.waterproofingdata.wpdauth.security.JwtTokenFilter;
import org.waterproofingdata.wpdauth.security.JwtTokenProvider;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class JwtTokenFilterConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilterConfigurer(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}

91
src/main/java/org/waterproofingdata/wpdauth/security/JwtTokenProvider.java

@ -0,0 +1,91 @@
package org.waterproofingdata.wpdauth.security;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.waterproofingdata.wpdauth.model.Roles;
import org.waterproofingdata.wpdauth.security.MyUserDetails;
import org.waterproofingdata.wpdauth.exception.CustomException;
@Component
public class JwtTokenProvider {
/**
* THIS IS NOT A SECURE PRACTICE! For simplicity, we are storing a static key here. Ideally, in a
* microservices environment, this key would be kept on a config-server.
*/
@Value("${security.jwt.token.secret-key:secret-key}")
private String secretKey;
@Value("${security.jwt.token.expire-length:3600000}")
private long validityInMilliseconds = 3600000; // 1h
@Autowired
private MyUserDetails myUserDetails;
@PostConstruct
protected void init() {
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
}
public String createToken(String username, List<Roles> roles) {
Claims claims = Jwts.claims().setSubject(username);
claims.put("auth", roles.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList()));
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
return Jwts.builder()//
.setClaims(claims)//
.setIssuedAt(now)//
.setExpiration(validity)//
.signWith(SignatureAlgorithm.HS256, secretKey)//
.compact();
}
public Authentication getAuthentication(String token) {
UserDetails userDetails = myUserDetails.loadUserByUsername(getUsername(token));
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
public String getUsername(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
throw new CustomException("Expired or invalid JWT token", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

35
src/main/java/org/waterproofingdata/wpdauth/security/MyUserDetails.java

@ -0,0 +1,35 @@
package org.waterproofingdata.wpdauth.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.waterproofingdata.wpdauth.model.Users;
import org.waterproofingdata.wpdauth.repository.UsersRepository;
@Service
public class MyUserDetails implements UserDetailsService {
@Autowired
private UsersRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final Users user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User '" + username + "' not found");
}
return org.springframework.security.core.userdetails.User//
.withUsername(username)//
.password(user.getPassword())//
.authorities(user.getRoles())//
.accountExpired(false)//
.accountLocked(false)//
.credentialsExpired(false)//
.disabled(false)//
.build();
}
}

78
src/main/java/org/waterproofingdata/wpdauth/security/WebSecurityConfig.java

@ -0,0 +1,78 @@
package org.waterproofingdata.wpdauth.security;
import org.waterproofingdata.wpdauth.security.JwtTokenFilterConfigurer;
import org.waterproofingdata.wpdauth.security.JwtTokenProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
// Disable CSRF (cross site request forgery)
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Entry points
http.authorizeRequests()//
.antMatchers("/users/signin").permitAll()//
.antMatchers("/users/signup").permitAll()//
.antMatchers("/h2-console/**/**").permitAll()
// Disallow everything else..
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
http.exceptionHandling().accessDeniedPage("/login");
// Apply JWT
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
// Optional, if you want to test the API from a browser
// http.httpBasic();
}
@Override
public void configure(WebSecurity web) throws Exception {
// Allow swagger to be accessed without authentication
web.ignoring().antMatchers("/v2/api-docs")//
.antMatchers("/swagger-resources/**")//
.antMatchers("/swagger-ui.html")//
.antMatchers("/configuration/**")//
.antMatchers("/webjars/**")//
.antMatchers("/public")
// Un-secure H2 Database (for testing purposes, H2 console shouldn't be unprotected in production)
.and()
.ignoring()
.antMatchers("/h2-console/**/**");;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Loading…
Cancel
Save