transferred token auth files

This commit is contained in:
Rohan Sircar 2019-11-18 10:49:02 +05:30
parent a91a142685
commit 1ecbc91e0e
11 changed files with 295 additions and 73 deletions

View File

@ -1,5 +1,7 @@
package org.ros.chatto; package org.ros.chatto;
import java.security.SecureRandom;
import org.modelmapper.ModelMapper; import org.modelmapper.ModelMapper;
import org.ros.chatto.security.AuthenticationSuccessHandlerImpl; import org.ros.chatto.security.AuthenticationSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -8,6 +10,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.security.core.token.KeyBasedPersistenceTokenService;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@PropertySource(value = "classpath:queries.properties") @PropertySource(value = "classpath:queries.properties")
@ -22,7 +26,6 @@ public class BeanConfigurations {
@Value("${spring.datasource.password}") @Value("${spring.datasource.password}")
private String password; private String password;
@Bean @Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() { public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new AuthenticationSuccessHandlerImpl(); return new AuthenticationSuccessHandlerImpl();
@ -33,17 +36,27 @@ public class BeanConfigurations {
ModelMapper modelMapper = new ModelMapper(); ModelMapper modelMapper = new ModelMapper();
return modelMapper; return modelMapper;
} }
@Bean @Bean
public MessageSource messageSource() { public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/messages,file:./config/messages"); messageSource.setBasenames("classpath:/messages,file:./config/messages");
messageSource.setUseCodeAsDefaultMessage(true); messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8"); messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(5); messageSource.setCacheSeconds(5);
return messageSource; return messageSource;
} }
@Bean
public TokenService tokenService() {
KeyBasedPersistenceTokenService keyBasedPersistenceTokenService = new KeyBasedPersistenceTokenService();
keyBasedPersistenceTokenService.setPseudoRandomNumberBytes(10);
keyBasedPersistenceTokenService.setSecureRandom(new SecureRandom());
keyBasedPersistenceTokenService.setServerInteger(1);
keyBasedPersistenceTokenService.setServerSecret(":");
return keyBasedPersistenceTokenService;
}
// @Bean // @Bean
// public Connection connection() throws SQLException // public Connection connection() throws SQLException
// { // {

View File

@ -2,22 +2,24 @@ package org.ros.chatto;
import org.ros.chatto.logged.MyLogoutSuccessHandler; import org.ros.chatto.logged.MyLogoutSuccessHandler;
import org.ros.chatto.logged.MySimpleUrlAuthenticationSuccessHandler; import org.ros.chatto.logged.MySimpleUrlAuthenticationSuccessHandler;
import org.ros.chatto.security.CustomBasicAuthenticationFilter;
import org.ros.chatto.security.MyUserDetailsService; import org.ros.chatto.security.MyUserDetailsService;
import org.ros.chatto.security.TokenAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@ -29,15 +31,17 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private MyUserDetailsService myUserDetailsService; private MyUserDetailsService myUserDetailsService;
@Autowired @Autowired
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@Autowired
private UserCache userCache;
// @SuppressWarnings("deprecation") @Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean @Bean
public AuthenticationProvider authenticationProvider() { public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(myUserDetailsService); provider.setUserDetailsService(myUserDetailsService);
provider.setUserCache(userCache);
provider.setPasswordEncoder(passwordEncoder); provider.setPasswordEncoder(passwordEncoder);
return provider; return provider;
} }
@ -52,6 +56,12 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
public static class ApiWebSecurity extends WebSecurityConfigurerAdapter { public static class ApiWebSecurity extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint; private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private CustomBasicAuthenticationFilter customBasicAuthFilter;
@Autowired
private TokenAuthenticationFilter tokenFilter;
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
@ -76,6 +86,14 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// .and() // .and()
// .logout(); // .logout();
; ;
http.addFilterBefore(tokenFilter, BasicAuthenticationFilter.class);
// Creating token when basic authentication is successful and the same token can
// be used to authenticate for further requests
// final CustomBasicAuthenticationFilter customBasicAuthFilter = new CustomBasicAuthenticationFilter(
// authenticationManagerBean());
http.addFilter(customBasicAuthFilter);
} }
@ -143,7 +161,6 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// .clearAuthentication(true) // .clearAuthentication(true)
// .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) // .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
// .logoutSuccessUrl("/").permitAll(); // .logoutSuccessUrl("/").permitAll();
} }
// @Override // @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception { // protected void configure(AuthenticationManagerBuilder auth) throws Exception {

View File

@ -1,47 +0,0 @@
package org.ros.chatto.config;
import org.ros.chatto.security.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.cache.SpringCacheBasedUserCache;
@EnableCaching
@Configuration
public class CacheConfig {
@Autowired
private CacheManager cacheManager;
@Bean
public UserCache userCache() throws Exception {
// return new EhCacheBasedUserCache();
// Cache cache = (Cache) cacheManager().getCache("userCache");
Cache cache = cacheManager.getCache("chatUser");
return new SpringCacheBasedUserCache(cache);
}
// private net.sf.ehcache.CacheManager cacheManager;
// @PreDestroy
// public void destroy() {
// cacheManager.shutdown();
// }
//
// @Bean
// public CacheManager cacheManager() {
//// log.debug("Starting Ehcache");
// cacheManager = net.sf.ehcache.CacheManager.create();
// cacheManager.getConfiguration().setMaxBytesLocalHeap("16M");
// EhCacheCacheManager ehCacheManager = new EhCacheCacheManager();
// ehCacheManager.setCacheManager(cacheManager);
// return ehCacheManager;
// }
}

View File

@ -0,0 +1,10 @@
package org.ros.chatto.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@EnableCaching
@Configuration
public class EhCacheConfig {
}

View File

@ -0,0 +1,31 @@
package org.ros.chatto.model;
import java.io.Serializable;
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;
@Data
@Entity
@Table(name="tokens")
public class UserToken implements Serializable {
/**
*
*/
private static final long serialVersionUID = -201675581183933341L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "token_id")
private long tokenID;
private String userName;
private String tokenContent;
private String role;
}

View File

@ -0,0 +1,19 @@
package org.ros.chatto.repository;
import org.ros.chatto.model.UserToken;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
@CacheConfig(cacheNames = "userTokenCache")
public interface TokenRepository extends JpaRepository<UserToken, Long> {
@Cacheable(value = "userTokenCache", key = "#token")
@Query("select t from UserToken t where t.tokenContent = ?1")
public UserToken findByToken(String token);
@Cacheable(value = "userTokenCache", key = "#userName")
@Query("select t from UserToken t where t.userName = ?1")
public UserToken findByUserName(String userName);
}

View File

@ -0,0 +1,66 @@
package org.ros.chatto.security;
import org.ros.chatto.model.UserToken;
import org.ros.chatto.repository.UserRepository;
import org.ros.chatto.service.UserService;
import org.ros.chatto.service.UserTokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.token.Token;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomBasicAuthenticationFilter extends BasicAuthenticationFilter {
@Autowired
private UserService userService;
@Autowired
private TokenService tokenService;
@Autowired
private UserTokenService userTokenService;
@Autowired
private UserRepository userRepository;
@Autowired
public CustomBasicAuthenticationFilter(final AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void onSuccessfulAuthentication(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response, final Authentication authResult) {
// Generate Token
// Save the token for the logged in user
// send token in the response
// String tokenString = UUID.randomUUID().toString();
// System.out.println("Role = " + authResult.getAuthorities().iterator().next().getAuthority());
UserToken userToken = userTokenService.getToken(authResult.getName());
Token token;
if (userToken == null) {
token = tokenService.allocateToken("");
userToken = new UserToken();
System.out.println("srwrrrrrrrrrrrr = " + authResult.getName());
// ChatUser user = userService.findByUserName(authResult.getName());
// ChatUser user = userRepository.findByUserName("hmm");
userToken.setTokenContent(token.getKey());
// userToken.setTokenContent(tokenString);
userToken.setUserName(authResult.getName());
userToken.setRole(authResult.getAuthorities().iterator().next().getAuthority());
userTokenService.saveToken(userToken);
response.setHeader("X-AUTH-TOKEN", token.getKey());
}
else {
token = tokenService.verifyToken(userToken.getTokenContent());
if(token!=null) {
response.setHeader("X-AUTH-TOKEN", token.getKey());
}
}
}
}

View File

@ -72,14 +72,6 @@ public class MyUserDetailsService implements UserDetailsService {
// } // }
System.out.println("Test from userdetails"); System.out.println("Test from userdetails");
ValueWrapper valueWrapper = cacheManager.getCache("chatUser").get("hmm");
if (valueWrapper != null) {
UserDetails userDetails = (UserDetails) valueWrapper.get();
if (userDetails != null) {
System.out.println("cache username = " + userDetails.getUsername());
System.out.println("cache password = " + userDetails.getPassword());
}
}
if (userRoles.size() == 0) { if (userRoles.size() == 0) {
throw new UsernameNotFoundException(username); throw new UsernameNotFoundException(username);
} }

View File

@ -0,0 +1,88 @@
package org.ros.chatto.security;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.ros.chatto.model.UserToken;
import org.ros.chatto.repository.TokenRepository;
import org.ros.chatto.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
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;
@Component
public class TokenAuthenticationFilter extends GenericFilterBean {
@Autowired
UserRoleRepository userRoleRepository;
@Autowired
TokenRepository tokenRepository;
@Autowired
TokenService tokenService;
@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)
UserToken userToken = tokenRepository.findByToken(accessToken);
if (userToken == null) {
throw new UsernameNotFoundException("Token not associated with any user");
}
Token token = tokenService.verifyToken(userToken.getTokenContent());
if (token == null) {
throw new UsernameNotFoundException("Token not issued by us");
}
String userName = userToken.getUserName();
if (userName == null) {
throw new UsernameNotFoundException("User not found");
}
// List<UserRole> userRoles = userRoleRepository.findByUser(chatUser.getUserName());
// // Populate SecurityContextHolder by fetching relevant information using token
// final UserDetails userPrincipal = User.withUsername(chatUser.getUserName()).password(chatUser.getPassword())
// .roles(userRoles.stream().map(userRole -> {
//// System.out.println("role = " + userRole.getRole().getName());
// return userRole.getRole().getName();
// }).toArray(size -> new String[size])).build();
// final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
// userPrincipal, null, userPrincipal.getAuthorities());
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);
}
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,33 @@
package org.ros.chatto.service;
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.stereotype.Service;
@Service
public class UserTokenService {
@Autowired
private TokenRepository tokenRepository;
// @Cacheable
public UserToken getToken(String userName)
{
return tokenRepository.findByUserName(userName);
}
@Transactional
public void saveToken(UserToken userToken)
{
UserToken userToken2 = tokenRepository.findByToken(userToken.getTokenContent());
if(userToken2!=null) {
System.out.println("Found valid token");
return;
}
tokenRepository.save(userToken);
}
}

View File

@ -6,9 +6,9 @@
<jsr107:defaults enable-statistics="true" /> <jsr107:defaults enable-statistics="true" />
</service> </service>
<cache alias="chatUser"> <cache alias="userTokenCache">
<key-type>java.lang.String</key-type> <key-type>java.lang.String</key-type>
<value-type>org.springframework.security.core.userdetails.UserDetails</value-type> <value-type>org.ros.chatto.model.UserToken</value-type>
<expiry> <expiry>
<ttl unit="seconds">600</ttl> <ttl unit="seconds">600</ttl>
</expiry> </expiry>