I have a problem while trying to log-in and authentitace my user. After sending POST request from Postman an internal server error(500) occure, then i get that error in my command line:
2022-11-26 11:23:32.930 ERROR 16316 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause.
As i understand there's probably infinite loop in my code, but I unfortunaly don't know how to solve this.
Login endpoint that I'm trying to do:
`
#PostMapping("login")
public ResponseEntity<AuthResponseDTO> login(#RequestBody LoginDto loginDto){
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginDto.getUsername(),
loginDto.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = jwtGenerator.generateToken(authentication);
return new ResponseEntity<>(new AuthResponseDTO(token), HttpStatus.OK);
}
AuthResponseDTO:
#Data
public class AuthResponseDTO {
private String accessToken;
private String tokenType = "Bearer ";
public AuthResponseDTO(String accessToken) {
this.accessToken = accessToken;
}
}
SecurityConfig:
#Configuration
#EnableWebSecurity
#EnableMethodSecurity
public class SecurityConfig {
private JwtAuthEntryPoint authEntryPoint;
private CustomUserDetailsService userDetailsService;
#Autowired
public SecurityConfig(CustomUserDetailsService userDetailsService, JwtAuthEntryPoint authEntryPoint) {
this.userDetailsService = userDetailsService;
this.authEntryPoint = authEntryPoint;
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(authEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public JWTAuthenticationFilter jwtAuthenticationFilter() {
return new JWTAuthenticationFilter();
}
}
`
JWTGenerator:
`
#Component
public class JWTGenerator {
public String generateToken(Authentication authentication) {
String username = authentication.getName();
Date currentDate = new Date();
Date expireDate = new Date(currentDate.getTime() + SecurityConstants.JWT_EXPIRATION);
String token = Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, SecurityConstants.JWT_SECRET)
.compact();
return token;
}
public String getUsernameFromJWT(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SecurityConstants.JWT_SECRET)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SecurityConstants.JWT_SECRET).parseClaimsJws(token);
return true;
} catch (Exception ex) {
throw new AuthenticationCredentialsNotFoundException("JWT was expired or incorrect");
}
}
}
`
As i said before, I don't know how to solve that problem. I expected to get data from AuthResponseDTO in order to get my JWT token.
Related
Hi i am new member of stackoverflow, i had a problem with my springboot project.Im trying to redirect after login google is successful, but its always show "There was an unexpected error (type=Not Found, status=404).
This is my configuration:
#Configuration
#EnableWebSecurity
#Order(2)
#PropertySource("classpath:application.properties")
public class ConfigSecuriry extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/login/**",
"/login/oauth2/code/google",
"/login/google",
"/api/token/refresh",
"**/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/swagger-resources",
"/swagger-resources/configuration/ui",
"/swagger-resources/configuration/security"
).permitAll();
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login/google")
.defaultSuccessUrl("/abc")
.successHandler(savedRequestAwareAuthenticationSuccessHandler())
.and()
.oauth2Client();
}
private SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler
= new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setDefaultTargetUrl("/abc"); // The URL to redirect to after a successful login
successHandler.setAlwaysUseDefaultTargetUrl(true);
return successHandler;
}
#Bean
public static ClientRegistrationRepository clientRegistrationRepository() {
ClientRegistration registration = ClientRegistration.withRegistrationId("google")
.clientId("XXXXXXXX")
.clientSecret("XXXXXXX")
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
return new InMemoryClientRegistrationRepository(registration);
}
}
and this is my controller:
#RestController
public class LoginGoogle {
#GetMapping("/abc")
public String sucess(){
return "Succes login google";
}
private final OAuth2AuthorizedClientService authorizedClientService;
public LoginGoogle(OAuth2AuthorizedClientService authorizedClientService) {
this.authorizedClientService = authorizedClientService;
}
#GetMapping("/login/google")
public RedirectView googleLogin(HttpServletRequest request) throws Exception {
String redirectUri = UriComponentsBuilder.fromHttpUrl(getBaseUrl(request))
.path("/login/oauth2/code/google")
.toUriString();
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(),
new JacksonFactory(),
"XXXXXXXX",
"XXXXXXXX",
Arrays.asList("email", "profile"))
.setAccessType("offline")
.build();
String url = flow.newAuthorizationUrl()
.setRedirectUri(redirectUri)
.setAccessType("offline")
.setApprovalPrompt("force")
.build();
return new RedirectView(url);
}
private String getBaseUrl(HttpServletRequest request) {
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
}
}
i was try anything i found but it doesn't seem to work.I look forward to receiving your contributions,thank you for all your assistance
I try to do the security of my project adapting the baeldung documentation and the previous code, and I want to know the normal method of this. I have the following configuration
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig {
#Autowired
private UserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private PasswordEncoder passwordEncoder;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Bean
public AuthenticationManager authenticationManager(HttpSecurity httpSecurity) throws Exception{
return httpSecurity.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder)
.and()
.build();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.cors()
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/user/create", "/api/login", "/swagger-ui/**", "/v3/api-docs/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic();
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
then I have this token provider
#Component
public class JtwTokenProvider {
#Value("${app.jwt-secret}")
private String jwtSecret;
#Value("${app.jwt-expiration-milliseconds}")
private int jwtExpirationInMs;
public String generateToken(Authentication authentication) {
String username = authentication.getName();
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtExpirationInMs);
String token = Jwts.builder().setSubject(username).setIssuedAt(new Date())
.setExpiration(expiryDate).signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
return token;
}
public String getUsernameOfJwt(String token){
Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
return claims.getSubject();
}
public boolean validateToken(String token){
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
return true;
}catch (SignatureException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid JWT signature");
}catch (MalformedJwtException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid JWT token");
}catch (ExpiredJwtException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Expired JWT token");
}catch (UnsupportedJwtException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Unsupported JWT token");
}catch (IllegalArgumentException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "JWT claims string is empty");
}
}
}
The token filter is the same and this manner is okay? What others exist?
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private JtwTokenProvider tokenProvider;
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//Get JWT from request
String token = getJwtFromRequest(request);
if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
// Get username from token
String username = tokenProvider.getUsernameOfJwt(token);
// Load user associated with the token
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//Set the authentication in the SecurityContext
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.replace("Bearer ", "");
}
return null;
}
}
Then I used the userdetails service
#Service
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username).orElseThrow(
() -> new NotFoundException("User not found"));
return new org.springframework.security.core.userdetails.User(user.getUsername(),
user.getPassword(), getAuthority(user.getRoles()));
}
private Collection<? extends GrantedAuthority> getAuthority(Set<Role> roles){
return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
Finally here is my authentication, this is safe? what is the standart manner of do the same?
#Service
public class LoginServiceImpl implements LoginService{
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JtwTokenProvider jwtTokenProvider;
#Override
public JwtAuthResponse login(LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(),
loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtTokenProvider.generateToken(authentication);
return new JwtAuthResponse(jwt);
}
}
I was waiting your responses thanks :D
I use spring boot with thymeleaf, spring security and spring cloud gateway.
User enter login/password and get a token. I search a way to get this tokin and put it in a cookie or in a hidden field in fragment. Need to to do some ajax call from thymeleaf page.
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
public class WebFluxSecurityConfig {
#Autowired
private WebFluxAuthManager authManager;
#Autowired
private WebFluxSecurityContextRepository webFluxSecurityContextRepository;
#Bean
protected SecurityWebFilterChain securityFilterChange(ServerHttpSecurity http) throws Exception {
http.csrf().disable()
.securityContextRepository(webFluxSecurityContextRepository)
.authorizeExchange()
// URL that starts with / or /login/
.pathMatchers("/", "/login", "/js/**", "/img/**", "/css/**").permitAll()
.anyExchange().authenticated()
.and().formLogin().loginPage("/login")
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/two")
).and().csrf().disable();
http.authenticationManager(authManager);
return http.build();
}
}
#Component
public class WebFluxSecurityContextRepository implements ServerSecurityContextRepository {
private final WebFluxAuthManager authManager;
public WebFluxSecurityContextRepository(WebFluxAuthManager authManager) {
this.authManager = authManager;
}
#Override
public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
return Mono.empty();
}
#Override
public Mono<SecurityContext> load(ServerWebExchange exchange) {
ServerHttpRequest request = exchange.getRequest();
String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
return this.authManager.authenticate(auth).map((authentication) -> {
return new SecurityContextImpl(authentication);
});
} else {
return Mono.empty();
}
}
}
#Component
public class WebFluxAuthManager implements ReactiveAuthenticationManager {
#Value("${gateway.url}")
private String gatewayUrl;
#Autowired
private WebClient webClient;
#Override
public Mono<Authentication> authenticate(Authentication authentication) {
Mono<ResponseEntity<String>> mResponse = webClient.post()
.uri("/auth/login")
.acceptCharset(Charset.forName("UTF-8"))
.body(Mono.just(loginRequest), LoginDto.class)
.retrieve()
.toEntity(String.class);
...
...
return Mono.just(new UsernamePasswordAuthenticationToken(username, password, authorities));
}
Just started using Jwt tokens when securing my microservices and keep getting a null token in my JwtTokenFilter class when a request is sent in but don't know where from, and finding it hard to understand why?
JwtTokenFilter.class
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(request);
System.out.println("Token: " + token);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (CustomException ex) {
SecurityContextHolder.clearContext();
response.sendError(ex.getHttpStatus().value(), ex.getMessage());
return;
}
filterChain.doFilter(request, response);
}
SecurityConfig.class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtTokenProvider jwtTokenProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/login").permitAll()
.antMatchers("/auth/register").permitAll()
.antMatchers("/auth/{username}").permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(new JwtTokenFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}
JwtTokenProvider.class
#Component
public class JwtTokenProvider {
#Value("$security.jwt.token.secret-key")
private String secretKey;
private long validityInMilliseconds = 3600000;
#Autowired
private CustomUserDetails customUserDetails;
#PostConstruct
protected void init() {
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
}
public String createToken(String username, List<Role> roles) {
Claims claims = Jwts.claims().setSubject(username);
claims.put("auth", roles.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).collect(Collectors.toList()));
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
return Jwts.builder()//
.setClaims(claims)//
.setIssuedAt(now)//
.setExpiration(validity)//
.signWith(SignatureAlgorithm.HS256, secretKey)//
.compact();
}
public Authentication getAuthentication(String token) {
UserDetails userDetails = customUserDetails.loadUserByUsername(getUsername(token));
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
public String getUsername(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
throw new CustomException("Expired or invalid JWT token", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
If you need any more classes shown just ask, thanks for the help.
Realised the problem was how I registered it with my Gateway microservice in the spring configuration. All sorted thanks for the help.
In my current project I have two separate entities.
User :- TO authenticate users
Customer :- To authenticate customers
I'm confuse How will we manage login process in same project for two separate entities by spring security?
As of now its working with one User entity , now i have to integrate one more login for customers with the help of Customer table.
is it possible ?
Note :- Due to some another requirement i can't use the same table for both users and customer.
I am sharing some code for more clearance.
Below code is the implementation of user detail service.
private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);
private final UserLoginRepository userRepository;
public DomainUserDetailsService(UserLoginRepository userRepository) {
this.userRepository = userRepository;
}
#Override
#Transactional
public UserDetails loadUserByUsername(final String login) {
log.debug("Authenticating {}", login);
if (new EmailValidator().isValid(login, null)) {
Optional<User> userByEmailFromDatabase = userRepository.findOneWithAuthoritiesByLogin(login);
return userByEmailFromDatabase.map(user -> createSpringSecurityUser(login, user))
.orElseThrow(() -> new UsernameNotFoundException("User with email " + login + " was not found in the database"));
}
String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
Optional<User> userByLoginFromDatabase = userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin);
return userByLoginFromDatabase.map(user -> createSpringSecurityUser(lowercaseLogin, user))
.orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
}
private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, User user) {
List<GrantedAuthority> grantedAuthorities = user.getAuthorities().stream()
.map(authority -> new SimpleGrantedAuthority(authority.getName()))
.collect(Collectors.toList());
return new org.springframework.security.core.userdetails.User(user.getLogin(),
user.getPassword(),
grantedAuthorities);
}
}
Below is the implantation of security config class.
private final AuthenticationManagerBuilder authenticationManagerBuilder;
private final UserDetailsService userDetailsService;
private final TokenProvider tokenProvider;
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, UserDetailsService userDetailsService,TokenProvider tokenProvider,CorsFilter corsFilter, SecurityProblemSupport problemSupport) {
this.authenticationManagerBuilder = authenticationManagerBuilder;
this.userDetailsService = userDetailsService;
this.tokenProvider = tokenProvider;
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
}
#PostConstruct
public void init() {
try {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
} catch (Exception e) {
throw new BeanInitializationException("Security configuration failed", e);
}
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/swagger-ui/index.html");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.csrf()
.disable()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/activate").permitAll()
.antMatchers("/api/userLogin").permitAll()
.antMatchers("/api/account/reset-password/init").permitAll()
.antMatchers("/api/account/reset-password/finish").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/v2/api-docs/**").permitAll()
.antMatchers("/swagger-resources/configuration/ui").permitAll()
.antMatchers("/swagger-ui/index.html").hasAuthority(AuthoritiesConstants.ADMIN)
.and()
.apply(securityConfigurerAdapter());
}
private JWTConfigurer securityConfigurerAdapter() {
return new JWTConfigurer(tokenProvider);
}
}
Login api
#PostMapping("/userLogin")
#Timed
public Response<JWTToken> authorize(
#Valid #RequestBody UserLoginReq userLoginReq) {
Map<String, Object> responseData = null;
try {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
userLoginReq.getUsername(), userLoginReq.getPassword());
Authentication authentication = this.authenticationManager
.authenticate(authenticationToken);
SecurityContextHolder.getContext()
.setAuthentication(authentication);
}
Yes you can pass user type combined in userName, separated by a character like :
Example:
String userName=inputUserName +":APP_USER";
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userName, password);
in UserDetailsService.loadUserByUsername(userName)
first split get the userName part and also get userType part.
Now on userType base you can decide the user should be authenticate from which table.
String userNamePart = null;
if (userName.contains(":")) {
int colonIndex = userName.lastIndexOf(":");
userNamePart = userName.substring(0, colonIndex);
}
userNamePart = userNamePart == null ? userName : userNamePart;
String userTypePart = null;
if (userName.contains(":")) {
int colonIndex = userName.lastIndexOf(":");
userTypePart = userName.substring(colonIndex + 1, userName.length());
}
At first customer is also user, isn't it? So maybe simpler solution would be to create customer also as user (use some flag/db field usertype ={USER|CUSTOMER|...}). If you still need to manage two entities, your approach is right, but In your DetailService just implement the another method which will read customer entity and then create spring's User.
I faced the same problem too!
It gave a error message like following:
AuthenticationManager This predefined class will help you to achieve this.
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
To over come this issue we should use Qualifier!
Please go through the following link , it will guide you to use qualifier
This is my first answer give it a like!
https://developpaper.com/can-spring-security-dock-multiple-user-tables-at-the-same-time/
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Primary
UserDetailsService us1() {
return new InMemoryUserDetailsManager(User.builder().username("javaboy").password("{noop}123").roles("admin").build());
}
#Bean
UserDetailsService us2() {
return new InMemoryUserDetailsManager(User.builder().username("sang").password("{noop}123").roles("user").build());
}
#Override
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
DaoAuthenticationProvider dao1 = new DaoAuthenticationProvider();
dao1.setUserDetailsService(us1());
DaoAuthenticationProvider dao2 = new DaoAuthenticationProvider();
dao2.setUserDetailsService(us2());
ProviderManager manager = new ProviderManager(dao1, dao2);
return manager;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/hello").hasRole("user")
.antMatchers("/admin").hasRole("admin")
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.permitAll()
.and()
.csrf().disable();
}
}