diff --git a/chatto/src/main/java/org/ros/chatto/model/UserToken.java b/chatto/src/main/java/org/ros/chatto/model/UserToken.java index 6da2e14..5901307 100644 --- a/chatto/src/main/java/org/ros/chatto/model/UserToken.java +++ b/chatto/src/main/java/org/ros/chatto/model/UserToken.java @@ -1,14 +1,13 @@ package org.ros.chatto.model; import java.io.Serializable; +import java.time.Instant; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; import javax.persistence.Table; import lombok.Data; @@ -28,4 +27,5 @@ public class UserToken implements Serializable { private String userName; private String tokenContent; private String role; + private Instant creationTime; } diff --git a/chatto/src/main/java/org/ros/chatto/repository/TokenRepository.java b/chatto/src/main/java/org/ros/chatto/repository/TokenRepository.java index 67c06b6..230c862 100644 --- a/chatto/src/main/java/org/ros/chatto/repository/TokenRepository.java +++ b/chatto/src/main/java/org/ros/chatto/repository/TokenRepository.java @@ -1,21 +1,20 @@ package org.ros.chatto.repository; import org.ros.chatto.model.UserToken; -import org.springframework.cache.annotation.CacheConfig; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository -@CacheConfig(cacheNames = "userTokenCache") public interface TokenRepository extends JpaRepository { - + @Query("select t from UserToken t where t.tokenContent = ?1") public UserToken findByToken(String token); - + @Query("select t from UserToken t where t.userName = ?1") public UserToken findByUserName(String userName); + @Modifying @Query("delete from UserToken t where t.userName = ?1") public void deleteByUserName(String userName); diff --git a/chatto/src/main/java/org/ros/chatto/security/TokenAuthenticationFilter.java b/chatto/src/main/java/org/ros/chatto/security/TokenAuthenticationFilter.java index 2e9e867..d3c1b8a 100644 --- a/chatto/src/main/java/org/ros/chatto/security/TokenAuthenticationFilter.java +++ b/chatto/src/main/java/org/ros/chatto/security/TokenAuthenticationFilter.java @@ -1,6 +1,8 @@ package org.ros.chatto.security; import java.io.IOException; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -9,12 +11,12 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.ros.chatto.model.UserToken; -import org.ros.chatto.repository.TokenRepository; -import org.ros.chatto.repository.UserRoleRepository; import org.ros.chatto.service.UserTokenService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -22,37 +24,98 @@ import org.springframework.security.core.token.Token; import org.springframework.security.core.token.TokenService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; -import org.springframework.web.filter.GenericFilterBean; - +import org.springframework.web.filter.OncePerRequestFilter; @Component -public class TokenAuthenticationFilter extends GenericFilterBean { +public class TokenAuthenticationFilter extends OncePerRequestFilter { @Autowired private UserTokenService userTokenService; @Autowired - TokenService tokenService; + private TokenService tokenService; + + private final int tokenTimeoutDuration; + + public TokenAuthenticationFilter(@Value("${chatto.token.timeout-duration}") String tokenTimeoutDuration) { +// super(); + this.tokenTimeoutDuration = Integer.parseInt(tokenTimeoutDuration); + } + +// @Override +// public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) +// throws IOException, ServletException { +// final HttpServletRequest httpRequest = (HttpServletRequest) request; +// +// // extract token from header +// final String accessToken = httpRequest.getHeader("X-AUTH-TOKEN"); +// if (null != accessToken) { +// // get and check whether token is valid ( from DB or file wherever you are +// // storing the token) +// Token token = tokenService.verifyToken(accessToken); +// +// if (token == null) { +// throw new UsernameNotFoundException("Token not issued by us"); +// } +// UserToken userToken = userTokenService.getTokenByTokenString(accessToken); +// +// if (userToken == null) { +// throw new UsernameNotFoundException("Token not associated with any user"); +// } +// +// String userName = userToken.getUserName(); +// if (userName == null) { +// throw new UsernameNotFoundException("User not found"); +// } +// +// +// +// System.out.println("Timeout duration = " + tokenTimeoutDuration); +// boolean isTokenExpired = isTokenExpired(userToken); +// System.out.println("expired? " + isTokenExpired); +// if (!isTokenExpired) { +// userTokenService.saveToken(userToken); +// SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userToken.getRole()); +// List updatedAuthorities = new ArrayList(); +// updatedAuthorities.add(simpleGrantedAuthority); +// final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( +// userName, token.getKey(), updatedAuthorities); +// SecurityContextHolder.getContext().setAuthentication(authentication); +// } else { +// userTokenService.deleteToken(userToken.getUserName()); +// } +// +// } +// +// chain.doFilter(request, response); +// } + + private boolean isTokenExpired(UserToken userToken) { + Duration duration = Duration.between(userToken.getCreationTime(), Instant.now()); + long minutes = Math.abs(duration.toMinutes()); + if (minutes > tokenTimeoutDuration) { + return true; + } + return false; + } @Override - public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) - throws IOException, ServletException { - final HttpServletRequest httpRequest = (HttpServletRequest) request; + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { - // extract token from header - final String accessToken = httpRequest.getHeader("X-AUTH-TOKEN"); + final String accessToken = request.getHeader("X-AUTH-TOKEN"); if (null != accessToken) { // get and check whether token is valid ( from DB or file wherever you are // storing the token) Token token = tokenService.verifyToken(accessToken); - + if (token == null) { throw new UsernameNotFoundException("Token not issued by us"); } UserToken userToken = userTokenService.getTokenByTokenString(accessToken); if (userToken == null) { - throw new UsernameNotFoundException("Token not associated with any user"); + throw new UsernameNotFoundException("User not found"); } String userName = userToken.getUserName(); @@ -60,18 +123,25 @@ public class TokenAuthenticationFilter extends GenericFilterBean { throw new UsernameNotFoundException("User not found"); } - SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userToken.getRole()); - List updatedAuthorities = new ArrayList(); - updatedAuthorities.add(simpleGrantedAuthority); - - - - final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userName, token.getKey(), updatedAuthorities); - SecurityContextHolder.getContext().setAuthentication(authentication); + System.out.println("Timeout duration = " + tokenTimeoutDuration); + boolean isTokenExpired = isTokenExpired(userToken); + System.out.println("expired? " + isTokenExpired); + if (!isTokenExpired) { + userToken.setCreationTime(Instant.now()); + userTokenService.saveToken(userToken); + SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userToken.getRole()); + List updatedAuthorities = new ArrayList(); + updatedAuthorities.add(simpleGrantedAuthority); + final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userName, token.getKey(), updatedAuthorities); + SecurityContextHolder.getContext().setAuthentication(authentication); + } else { + userTokenService.deleteToken(userToken.getUserName()); + } } - chain.doFilter(request, response); + filterChain.doFilter(request, response); } } \ No newline at end of file diff --git a/chatto/src/main/java/org/ros/chatto/service/UserTokenService.java b/chatto/src/main/java/org/ros/chatto/service/UserTokenService.java index b3ecaba..2dc871e 100644 --- a/chatto/src/main/java/org/ros/chatto/service/UserTokenService.java +++ b/chatto/src/main/java/org/ros/chatto/service/UserTokenService.java @@ -5,10 +5,12 @@ import javax.transaction.Transactional; import org.ros.chatto.model.UserToken; import org.ros.chatto.repository.TokenRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service +@CacheConfig(cacheNames = "userTokenCache") public class UserTokenService { @Autowired private TokenRepository tokenRepository; @@ -16,6 +18,7 @@ public class UserTokenService { @Cacheable(value = "userTokenCache", key = "#userName", unless="#result == null") public UserToken getTokenByUserName(String userName) { + System.out.println("Inside 1"); return tokenRepository.findByUserName(userName); } @@ -23,17 +26,19 @@ public class UserTokenService { @Cacheable(value = "userTokenCache", key = "#tokenString", unless="#result == null") public UserToken getTokenByTokenString(String tokenString) { + System.out.println("Inside 2"); return tokenRepository.findByToken(tokenString); } @Transactional public void saveToken(UserToken userToken) { - UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent()); - if(userToken2!=null) { - System.out.println("Found valid token"); - return; - } +// UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent()); +// if(userToken2!=null) { +// System.out.println("Found valid token"); +// return; +// } +// System.out.println("Saving token"); tokenRepository.save(userToken); } diff --git a/chatto/src/main/resources/application.properties b/chatto/src/main/resources/application.properties index 64e4e4c..507d5af 100644 --- a/chatto/src/main/resources/application.properties +++ b/chatto/src/main/resources/application.properties @@ -26,4 +26,4 @@ spring.cache.jcache.config=classpath:ehcache.xml logging.level.org.springframework.cache = DEBUG #test.bindAddress=192.168.1.106 -chatto.token.timeout-duration=10_000 \ No newline at end of file +chatto.token.timeout-duration=30 \ No newline at end of file diff --git a/chatto/src/main/resources/ehcache.xml b/chatto/src/main/resources/ehcache.xml index 040a382..ee89592 100644 --- a/chatto/src/main/resources/ehcache.xml +++ b/chatto/src/main/resources/ehcache.xml @@ -10,7 +10,7 @@ java.lang.String org.ros.chatto.model.UserToken - 60 + 300