Implemented token expiry

Token expiry can be set from properties file

Also changed tokenauthfiter from genericfilterbean to
onceperrequestfiter
This commit is contained in:
Rohan Sircar 2019-11-20 14:09:12 +05:30
parent 25f55a6262
commit 8a339ddf83
6 changed files with 109 additions and 35 deletions

View File

@ -1,14 +1,13 @@
package org.ros.chatto.model; package org.ros.chatto.model;
import java.io.Serializable; import java.io.Serializable;
import java.time.Instant;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import lombok.Data; import lombok.Data;
@ -28,4 +27,5 @@ public class UserToken implements Serializable {
private String userName; private String userName;
private String tokenContent; private String tokenContent;
private String role; private String role;
private Instant creationTime;
} }

View File

@ -1,14 +1,12 @@
package org.ros.chatto.repository; package org.ros.chatto.repository;
import org.ros.chatto.model.UserToken; 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.JpaRepository;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
@CacheConfig(cacheNames = "userTokenCache")
public interface TokenRepository extends JpaRepository<UserToken, Long> { public interface TokenRepository extends JpaRepository<UserToken, Long> {
@Query("select t from UserToken t where t.tokenContent = ?1") @Query("select t from UserToken t where t.tokenContent = ?1")
@ -16,6 +14,7 @@ public interface TokenRepository extends JpaRepository<UserToken, Long> {
@Query("select t from UserToken t where t.userName = ?1") @Query("select t from UserToken t where t.userName = ?1")
public UserToken findByUserName(String userName); public UserToken findByUserName(String userName);
@Modifying @Modifying
@Query("delete from UserToken t where t.userName = ?1") @Query("delete from UserToken t where t.userName = ?1")
public void deleteByUserName(String userName); public void deleteByUserName(String userName);

View File

@ -1,6 +1,8 @@
package org.ros.chatto.security; package org.ros.chatto.security;
import java.io.IOException; import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -9,12 +11,12 @@ import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ros.chatto.model.UserToken; 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.ros.chatto.service.UserTokenService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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;
@ -22,25 +24,86 @@ import org.springframework.security.core.token.Token;
import org.springframework.security.core.token.TokenService; import org.springframework.security.core.token.TokenService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.filter.OncePerRequestFilter;
@Component @Component
public class TokenAuthenticationFilter extends GenericFilterBean { public class TokenAuthenticationFilter extends OncePerRequestFilter {
@Autowired @Autowired
private UserTokenService userTokenService; private UserTokenService userTokenService;
@Autowired @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<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
// 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 @Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException { throws ServletException, IOException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
// extract token from header final String accessToken = request.getHeader("X-AUTH-TOKEN");
final String accessToken = httpRequest.getHeader("X-AUTH-TOKEN");
if (null != accessToken) { if (null != accessToken) {
// get and check whether token is valid ( from DB or file wherever you are // get and check whether token is valid ( from DB or file wherever you are
// storing the token) // storing the token)
@ -52,7 +115,7 @@ public class TokenAuthenticationFilter extends GenericFilterBean {
UserToken userToken = userTokenService.getTokenByTokenString(accessToken); UserToken userToken = userTokenService.getTokenByTokenString(accessToken);
if (userToken == null) { if (userToken == null) {
throw new UsernameNotFoundException("Token not associated with any user"); throw new UsernameNotFoundException("User not found");
} }
String userName = userToken.getUserName(); String userName = userToken.getUserName();
@ -60,18 +123,25 @@ public class TokenAuthenticationFilter extends GenericFilterBean {
throw new UsernameNotFoundException("User not found"); throw new UsernameNotFoundException("User not found");
} }
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userToken.getRole()); System.out.println("Timeout duration = " + tokenTimeoutDuration);
List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>(); boolean isTokenExpired = isTokenExpired(userToken);
updatedAuthorities.add(simpleGrantedAuthority); System.out.println("expired? " + isTokenExpired);
if (!isTokenExpired) {
userToken.setCreationTime(Instant.now());
userTokenService.saveToken(userToken);
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userName, token.getKey(), updatedAuthorities); SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(userToken.getRole());
SecurityContextHolder.getContext().setAuthentication(authentication); List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
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);
} }
} }

View File

@ -5,10 +5,12 @@ import javax.transaction.Transactional;
import org.ros.chatto.model.UserToken; import org.ros.chatto.model.UserToken;
import org.ros.chatto.repository.TokenRepository; import org.ros.chatto.repository.TokenRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@CacheConfig(cacheNames = "userTokenCache")
public class UserTokenService { public class UserTokenService {
@Autowired @Autowired
private TokenRepository tokenRepository; private TokenRepository tokenRepository;
@ -16,6 +18,7 @@ public class UserTokenService {
@Cacheable(value = "userTokenCache", key = "#userName", unless="#result == null") @Cacheable(value = "userTokenCache", key = "#userName", unless="#result == null")
public UserToken getTokenByUserName(String userName) public UserToken getTokenByUserName(String userName)
{ {
System.out.println("Inside 1");
return tokenRepository.findByUserName(userName); return tokenRepository.findByUserName(userName);
} }
@ -23,17 +26,19 @@ public class UserTokenService {
@Cacheable(value = "userTokenCache", key = "#tokenString", unless="#result == null") @Cacheable(value = "userTokenCache", key = "#tokenString", unless="#result == null")
public UserToken getTokenByTokenString(String tokenString) public UserToken getTokenByTokenString(String tokenString)
{ {
System.out.println("Inside 2");
return tokenRepository.findByToken(tokenString); return tokenRepository.findByToken(tokenString);
} }
@Transactional @Transactional
public void saveToken(UserToken userToken) public void saveToken(UserToken userToken)
{ {
UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent()); // UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent());
if(userToken2!=null) { // if(userToken2!=null) {
System.out.println("Found valid token"); // System.out.println("Found valid token");
return; // return;
} // }
// System.out.println("Saving token");
tokenRepository.save(userToken); tokenRepository.save(userToken);
} }

View File

@ -26,4 +26,4 @@ spring.cache.jcache.config=classpath:ehcache.xml
logging.level.org.springframework.cache = DEBUG logging.level.org.springframework.cache = DEBUG
#test.bindAddress=192.168.1.106 #test.bindAddress=192.168.1.106
chatto.token.timeout-duration=10_000 chatto.token.timeout-duration=30

View File

@ -10,7 +10,7 @@
<key-type>java.lang.String</key-type> <key-type>java.lang.String</key-type>
<value-type>org.ros.chatto.model.UserToken</value-type> <value-type>org.ros.chatto.model.UserToken</value-type>
<expiry> <expiry>
<ttl unit="seconds">60</ttl> <ttl unit="seconds">300</ttl>
</expiry> </expiry>
<listeners> <listeners>
<listener> <listener>