Implemented token expiry
Token expiry can be set from properties file Also changed tokenauthfiter from genericfilterbean to onceperrequestfiter
This commit is contained in:
parent
25f55a6262
commit
8a339ddf83
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
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")
|
||||||
public UserToken findByToken(String token);
|
public UserToken findByToken(String token);
|
||||||
|
|
||||||
@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);
|
||||||
|
@ -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,37 +24,98 @@ 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)
|
||||||
Token token = tokenService.verifyToken(accessToken);
|
Token token = tokenService.verifyToken(accessToken);
|
||||||
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
throw new UsernameNotFoundException("Token not issued by us");
|
throw new UsernameNotFoundException("Token not issued by us");
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user