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;
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;
}

View File

@ -1,14 +1,12 @@
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<UserToken, Long> {
@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")
public UserToken findByUserName(String userName);
@Modifying
@Query("delete from UserToken t where t.userName = ?1")
public void deleteByUserName(String userName);

View File

@ -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,25 +24,86 @@ 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<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
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)
@ -52,7 +115,7 @@ public class TokenAuthenticationFilter extends GenericFilterBean {
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");
}
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<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
updatedAuthorities.add(simpleGrantedAuthority);
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userName, token.getKey(), updatedAuthorities);
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.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);
}

View File

@ -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
chatto.token.timeout-duration=30

View File

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