I have a problem, I'm testing an api with spring boot and oauth2, but when requesting the token the same is generated and sent to the browser, however when sending to the resource I only get access danied, below the codes:
ServerAuthorizationApplication
package br.com.serverAuthorization;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ServerAuthorizationApplication {
public static void main(String[] args) {
SpringApplication.run(ServerAuthorizationApplication.class, args);
}
}
AuthorizationServerConfig
package br.com.serverAuthorization.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
public static final String RESOURCE_ID = "arip";
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore()).authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.checkTokenAccess("hasRole('CLIENT')");
}
#Override
public void configure(ClientDetailsServiceConfigurer client) throws Exception {
client.inMemory()
.withClient("clientapp")
.secret("123456")
.authorizedGrantTypes("password")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.and()
.withClient("clientcred")
.secret("123456")
.authorizedGrantTypes("client_credentials")
.scopes("trust")
.resourceIds(RESOURCE_ID)
.and()
.withClient("clientauthcode")
.secret("123456")
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.and()
.withClient("jsclient")
.secret("123456")
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.authorities("CLIENT")
.redirectUris("http://localhost:8080/contacts")
.accessTokenValiditySeconds(3600)
.autoApprove(true);
}
}
ResourceServerConfig
package br.com.serverAuthorization.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "arip";
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/contacts").hasRole("ADMIN");
//http.authorizeRequests().antMatchers("/api/staff").hasRole("STAFF");
//http.authorizeRequests().antMatchers("/api/client").access("#oauth2.hasScope('trust')");
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId("jsclient");
tokenService.setClientSecret("123456");
tokenService.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
resources.resourceId(RESOURCE_ID).tokenServices(tokenService);
}
}
SecurityConfig
package br.com.serverAuthorization.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("passw0rd").roles("ADMIN");
auth.inMemoryAuthentication().withUser("staff").password("passw0rd").roles("STAFF");
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/contacts").authenticated();
}
}
HomeController
package br.com.serverAuthorization.controllers;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import br.com.serverAuthorization.models.Contact;
#RestController
#RequestMapping("/contacts")
public class HomeController {
private List<Contact> listContact = new ArrayList<Contact>();
#GetMapping
public ResponseEntity<Principal> listAll(Principal user){
System.out.println("Entro");
listContact.add(new Contact(1, "Marcos Paulo Souza Miranda", "marcospsmiranda#gmail.com"));
listContact.add(new Contact(2, "João Pedro Souza Miranda", "joaopedro#gmail.com"));
listContact.add(new Contact(3, "Radames Aurelio Miranda", "radames#gmail.com"));
listContact.add(new Contact(4, "Lucelia de Souza Silva Miranda", "lucelia#gmail.com"));
return new ResponseEntity<>(user, HttpStatus.OK);
}
}
Contact
package br.com.serverAuthorization.models;
public class Contact {
private Integer id;
private String nome;
private String email;
public Contact(Integer id, String nome, String email) {
super();
this.id = id;
this.nome = nome;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 21 days ago.
Improve this question
I've been trying to create a spring security logic to authorize users (inserted into my database) to do different things based on their roles (simple). I'm supposed to have ROLE_USER and ROLE_ADMIN, but I don't think any of them work. Please help. I'll try to put every bit of important code here (even the imports).
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import com.vitoria.enums.RoleName;
#Entity
#Table(name = "TB_ROLE")
public class RoleModel implements GrantedAuthority, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID roleId;
#Enumerated(EnumType.STRING)
#Column(nullable = false, unique = true)
private RoleName roleName;
#Override
public String getAuthority() {
return this.roleName.toString();
}
public UUID getRoleId() {
return roleId;
}
public void setRoleId(UUID roleId) {
this.roleId = roleId;
}
public RoleName getRoleName() {
return roleName;
}
public void setRoleName(RoleName roleName) {
this.roleName = roleName;
}
}
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
#Entity
#Table(name = "TB_USER")
public class UserModel implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID userId;
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false)
private String password;
#ManyToMany
#JoinTable(name = "TB_USERS_ROLES",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private List<RoleModel> roles;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles;
}
#Override
public String getPassword() {
return this.password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
public enum RoleName {
ROLE_ADMIN,
ROLE_USER;
}
import javax.transaction.Transactional;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
#Service
#Transactional
public class UserDetailsServiceImpl implements UserDetailsService {
final UserRepository userRepository;
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserModel userModel = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return new User(userModel.getUsername(), userModel.getPassword(), true, true, true,true, userModel.getAuthorities());
}
}
import org.springframework.data.jpa.repository.JpaRepository;
import com.vitoria.models.RoleModel;
public interface RoleRepository extends JpaRepository<RoleModel, Long> {
RoleModel findByRoleName(String roleName);
}
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.vitoria.models.UserModel;
#Repository
public interface UserRepository extends JpaRepository<UserModel, UUID> {
Optional<UserModel> findByUsername(String username);
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.csrf().disable();
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.Flowers;
import com.vitoria.repositories.FlowersRepository;
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#EnableAutoConfiguration
#RequestMapping("/flowers")
public class FlowersController {
#Autowired
private FlowersRepository repo;
#PreAuthorize("hasRole('ROLE_USER')")
#GetMapping
public ResponseEntity<List<Flowers>> findAll(){
List<Flowers> allFlowers=repo.findAll();
return ResponseEntity.ok().body(allFlowers);
}
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
#PostMapping("/insert")
public ResponseEntity<Flowers> insert(#RequestBody Flowers flower){
Flowers entity=flower;
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deleteById(#PathVariable Integer id){
repo.deleteById(id);
return ResponseEntity.noContent().build();
}
}
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository repo;
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
#GetMapping
public ResponseEntity<List<UserModel>> findAll(){
List<UserModel> users=repo.findAll();
return ResponseEntity.ok().body(users);
}
#PreAuthorize("hasRole('ROLE_USER')")
#GetMapping("/{username}")
public ResponseEntity<Optional<UserModel>> findByUsername(#RequestParam("username")String username){
Optional<UserModel> user=repo.findByUsername(username);
return ResponseEntity.ok().body(user);
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#PostMapping("/save")
public ResponseEntity<UserModel> insert(#RequestBody UserModel user){
UserModel entity=user;
user.setPassword(passwordEncoder().encode(user.getPassword()));
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
private PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
my database looks like this:
tb_user
tb_role
tb_users_roles
I think this is all.
Please keep in mind that when I try to make ->any<- request to any endpoint it comesback unauthorized. SO, I tried something else: taking off the role permission (using the #PreAuthorize("permitAll()")) of get all users and I still get 401 as return! Please please help me.
While hit login url in postman the above error occurs ..the concept is want to generate jwt token using cookies .am new to Springboot ..please help me to get out from this issue..The configuration am using was SpringBoot version:3.0.1 and java version 17
here i attach the configuration files used .
AuthEntryPointJwt.java:
import java.io.IOException;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
#Component
public class AuthEntryPointJwt extends ResponseEntityExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map<String, Object> body = Map.of("status", HttpServletResponse.SC_UNAUTHORIZED, "error", "Unauthorized",
"message", authException.getMessage(), "path", request.getServletPath());
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
}
AuthTokenFilter.java:
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import com.midfin.erp.impl.UserDetailsServiceImpl;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class AuthTokenFilter extends OncePerRequestFilter {
#Autowired
private JwtUtils jwtUtils;
#Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String jwt = jwtUtils.getJwtFromCookies(request);
return jwt;
}
}
JwtUtils.java:
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;
import com.midfin.erp.impl.UserDetailsImpl;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
#Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
#Value("${jwt.secret}")
private String jwtSecret;
#Value("${jwt.expirationMs}")
private int jwtExpirationMs;
#Value("${jwt.cookieName}")
private String jwtCookie;
public String getJwtFromCookies(HttpServletRequest request) {
Cookie cookie = WebUtils.getCookie(request, jwtCookie);
if (cookie != null) {
return cookie.getValue();
} else {
return null;
}
}
public ResponseCookie generateJwtCookie(UserDetailsImpl userPrincipal) {
String jwt = generateTokenFromUsername(userPrincipal.getUsername());
System.out.println(jwt);
ResponseCookie cookie = ResponseCookie.from(jwtCookie, jwt).path("/api").maxAge(24 * 60 * 60).httpOnly(true)
.build();
return cookie;
}
public ResponseCookie getCleanJwtCookie() {
ResponseCookie cookie = ResponseCookie.from(jwtCookie, null).path("/api").build();
return cookie;
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
logger.error("Invalid JWT signature: {}", e.getMessage());
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
public String generateTokenFromUsername(String username) {
return Jwts.builder().setSubject(username).setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}
}
WebSecurityConfig.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.midfin.erp.impl.UserDetailsServiceImpl;
#Configuration
#EnableMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder);
return authProvider;
}
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeHttpRequests().requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ROLE_ADMIN > ROLE_USER";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
UserDetailsImpl.java:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.midfin.erp.domain.UserPrivilege;
import com.midfin.erp.domain.UserRole;
import com.midfin.erp.domain.Users;
import lombok.Data;
#Data
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Long userId;
private String username;
private String email;
private String fullName;
private String mobileNumber;
private String password;
private boolean locked;
private Collection<? extends GrantedAuthority> authorities;
public UserDetailsImpl(Long userId, String username, String email, String password, String fullName,
String mobileNumber, Boolean locked, Collection<? extends GrantedAuthority> authorities) {
this.userId = userId;
this.username = username;
this.email = email;
this.password = password;
this.mobileNumber = mobileNumber;
this.fullName = fullName;
this.locked = locked;
this.authorities = authorities;
}
public static UserDetailsImpl build(Users user) {
List<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());
return new UserDetailsImpl(user.getUserId(), user.getUsername(), user.getEmail(), user.getPassword(),
user.getMobileNumber(), user.getFullName(), user.getIslocked(), authorities);
}
#Override
public String getPassword() {
return this.password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return !this.locked;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
private List<String> getPrivileges(Collection<UserRole> roles) {
List<String> privileges = new ArrayList<>();
List<UserPrivilege> collection = new ArrayList<>();
for (UserRole role : roles) {
privileges.add(role.getName());
collection.addAll(role.getPrivileges());
}
for (UserPrivilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
}
UserDetailsServiceImpl.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.midfin.erp.domain.Users;
import com.midfin.erp.repo.UserRepo;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
UserRepo userRepo;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = userRepo.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
}
}
If you look closely at your logs, you'll see something like this: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter
This is because the io.jsonwebtoken dependency uses javax.xml.bind.DatatypeConverter, but in spring version 3 it no longer uses the name javax but jakarta
As mentioned https://stackoverflow.com/a/75203778/9718846 you need to add the 0.11.5 dependencies. For maven, the answer is here : https://github.com/jwtk/jjwt#features
My Custom UserDetailsService
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import br.com.fimd.entidades.Usuario;
import br.com.fimd.service.UsuarioService;
#Transactional(readOnly=true)
#Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService{
#Autowired
private UsuarioService usuarioService;
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Usuario usuario = usuarioService.findUserByEmail(email);
if(usuario == null) {
throw new UsernameNotFoundException("Usuário nao encontrado.");
}
return new User(usuario.getEmail(), usuario.getSenha(), usuario.getAuthorities());
}
}
My Security Configuration
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsServiceImpl")
private UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().disable().
csrf().disable().authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers("/public/**").permitAll()
.antMatchers("/private/**").hasRole("USER")
//.antMatchers("/admin*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
My User Entity
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "usuarios")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true)
public class Usuario implements UserDetails, Serializable{
private static final long serialVersionUID = 4038437690572999966L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Long id;
#NotBlank
private String nome;
#NotBlank
private String email;
#NotBlank
private String senha;
#NotBlank
private String cpf;
#Column
private boolean ativo;
#ManyToMany
#JoinTable(name="perfil_usuario", joinColumns=
{#JoinColumn(name="user_id")}, inverseJoinColumns=
{#JoinColumn(name="tipo_perfil")})
private Set<Perfil> perfis = new HashSet<>();
#OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Investimento> investimentos;
#OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Extrato> extratos;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<Perfil> getPerfis() {
return perfis;
}
public void setPerfis(Set<Perfil> perfis) {
this.perfis = perfis;
}
public List<Investimento> getInvestimentos() {
return investimentos;
}
public void setInvestimentos(List<Investimento> investimentos) {
this.investimentos = investimentos;
}
public List<Extrato> getExtratos() {
return extratos;
}
public void setExtratos(List<Extrato> extratos) {
this.extratos = extratos;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.perfis;
}
#Override
public String getPassword() {
return this.senha;
}
#Override
public String getUsername() {
return this.email;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
My Perfil Entity
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.springframework.security.core.GrantedAuthority;
#Entity
public class Perfil implements GrantedAuthority{
private static final long serialVersionUID = 1L;
#Id
private String tipoPerfil;
#ManyToMany(mappedBy="perfis")
private List<Usuario> usuarios;
public List<Usuario> getUsuarios() {
return usuarios;
}
public void setUsuarios(List<Usuario> usuarios) {
this.usuarios = usuarios;
}
public String getTipoPerfil() {
return tipoPerfil;
}
public void setTipoPerfil(String tipoPerfil) {
this.tipoPerfil = tipoPerfil;
}
#Override
public String getAuthority() {
return this.tipoPerfil;
}
}
My Spring Filter Initializer
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
#Configuration
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
When i call a "/private/service" my loadUserByUsername not being called never, my application ever send me a 403 forbidden, access denied.
Why that?
I tried a lot of tutorials from internet and my code seems to be correct, i'm using spring starter 2.0.5.RELEASE
I already tried to call the userDetailsService from a #Bean method in SecurityConfiguration
Your security configuration is not complete, you must provide as well the login information:
.formLogin()
.loginPage("/login.html")
.defaultSuccessUrl("/home")
.failureUrl("/login.html?error=true")
Otherwise all your requests will be unauthorized. Please see this tutorial:
https://www.baeldung.com/spring-security-login
Your Custom UserDetails service will be called only when the application will receive a POST to login url with username and password, otherwise it will not have what data to authorize.
I've been debugging for 10 hours and can't seem to figure out why I'm continuously getting bad credentials errors within Spring Security.
I can actually see that I'm grabbing the user from the database in my userdetailsservice. The passwords match up correctly (not hashing/encoding anything currently), but as I dive into the framework, I get the mismatch creds exception.
I'm honestly out of ideas, I feel like I have rewritten this code 3-4 times now, but to no avail.
I'm hitting /login to generate the token.
Jwt Security Config
import com.schachte.asciiphile.security.messaging.JwtAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#Configuration
#Order(1)
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String ROOT_CTX_MATCH_PATH = "/phile/**";
#Autowired
private JwtAuthenticationEntryPoint entryPoint;
#Qualifier("userDetailsServiceImpl")
#Autowired
private UserDetailsService userDetailsService;
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(new JwtLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
Jwt Login Filter
import com.fasterxml.jackson.databind.ObjectMapper;
import com.schachte.asciiphile.model.JwtAuthententicationToken;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.security.util.JwtGenerator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.auth0.jwt.JWT;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import java.util.Date;
import java.util.List;
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {
private JwtGenerator jwtGenerator = new JwtGenerator();
private AuthenticationManager authenticationManager;
public JwtLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(
HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
User creds = null;
try {
creds = new ObjectMapper()
.readValue(req.getInputStream(), User.class);
} catch (IOException e) {
e.printStackTrace();
}
List<GrantedAuthority> grantedAuthorities = AuthorityUtils
.commaSeparatedStringToAuthorityList(creds.getRole());
return authenticationManager.authenticate(
new JwtAuthententicationToken(
creds.getUsername(),
creds.getPassword(),
grantedAuthorities
)
);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, auth);
String token = JWT.create()
.withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 864_000_000))
.sign(HMAC512("secret".getBytes()));
response.addHeader("Authorization", "Token " + token);
}
}
Jwt Authentication Token
import lombok.Data;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.List;
#Data
public class JwtAuthententicationToken extends UsernamePasswordAuthenticationToken {
private String username;
private String password;
private List<GrantedAuthority> grantedAuthorities;
public JwtAuthententicationToken(String username, String password, List<GrantedAuthority> grantedAuthorities) {
super(null, null);
this.username = username;
this.password = password;
this.grantedAuthorities = grantedAuthorities;
}
#Override
public Object getCredentials() {
return null;
}
#Override
public Object getPrincipal() {
return this.username;
}
}
Custom User Details
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class CustomUserDetails extends User implements UserDetails {
private Collection<? extends GrantedAuthority> authorities;
public CustomUserDetails(final User user, Collection<? extends GrantedAuthority> authorities) {
super(user);
this.authorities = authorities;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getUsername() {
return super.getUsername();
}
#Override
public String getPassword() {
return super.getPassword();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
User
import javax.persistence.*;
import lombok.Data;
#Entity
#Data
public class User {
public User() {}
public User(String username, String pass, String role) {
this.username = username;
this.password = pass;
this.role = role;
}
public User(User username) {
this.email = username.getEmail();
this.password = username.getPassword();
this.premium = username.getPremium();
this.storedBytes = username.getStoredBytes();
this.username = username.getUsername();
}
#Id
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "premium")
private int premium;
#Column(name = "storedbytes")
private int storedBytes;
#Column(name = "role")
private String role;
}
User Detail Service
import com.schachte.asciiphile.model.CustomUserDetails;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.repository.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Optional;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepo applicationUserRepository;
public UserDetailsServiceImpl(UserRepo applicationUserRepository) {
this.applicationUserRepository = applicationUserRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<User> applicationUser = applicationUserRepository.findByUsername(username);
if (!applicationUser.isPresent()) {
throw new UsernameNotFoundException(username);
}
return new CustomUserDetails(applicationUser.get(), AuthorityUtils
.commaSeparatedStringToAuthorityList(applicationUser.get().getRole()));
}
}
I'm just creating simple app using spring mvc, gradle, spring security, spring data jpa. Now I would like to test how spring security works, but I have a problem. First I show you little code then I will mention about my problem.
Structure:
Person.java
package com.test.business;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "person")
public class Person {
#Id
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "password")
private String password;
#Column(name = "role")
private String role;
public Person(){
}
public Person(int id, String name, String password, String role) {
this.id = id;
this.name = name;
this.password = password;
this.role = role;
}
//setters and getters
}
PersonController.java
package com.test.controller;
import com.test.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class PersonController {
#Autowired
private PersonService personService;
#GetMapping(value="/")
#ResponseBody
public String printWelcome() {
return "home";
}
#GetMapping(value="/admin")
#ResponseBody
public String admin() {
return "admin";
}
#GetMapping(value="/user")
#ResponseBody
public String user() {
return "user";
}
}
MyWebInitializer.java
package com.test.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class, SecurityConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
SecurityWebInitializer.java
package com.test.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebInitializer
extends AbstractSecurityWebApplicationInitializer {
}
RootConfig.java
package com.test.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableJpaRepositories( basePackages = {"com.test.repository"})
#PropertySource(value = { "classpath:application.properties" })
#EnableTransactionManagement
#Import({ SecurityConfig.class })
#ComponentScan(basePackages = {"com.test.service", "com.test.repository", "com.test.controller", "com.test.business"})
public class RootConfig {
#Autowired
private Environment environment;
#Autowired
private DataSource dataSource;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.test.business");
factory.setDataSource(dataSource());
factory.setJpaProperties(jpaProperties());
return factory;
}
private Properties jpaProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
}
WebConfig.java
package com.test.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#EnableWebMvc
#Configuration
#ComponentScan({ "com.test.controller" })
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp().prefix("/WEB-INF/views/").suffix(".jsp");
}
}
SecurityConfig.java
package com.test.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name, password"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name, role"
+ "from person where name=?");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN")
.and()
.httpBasic(); // Authenticate users with HTTP basic authentication
}
}
Record in DB as JSON:
{
"id": 1,
"name": "test1",
"password": "test1",
"role": "ADMIN"
}
And what's the problem? Look at SecurityConfig.java. There is jdbcAuthentication(). When I try access to /admin browser will ask me to put username and password. Unfortunately, when I do that nothing happend and browser will ask again, and again.
I changed a little me code. In SecurityConfig.java instead of jdbcAuthentication() I used inMemoryAuthentication() so it looked like:
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN")
.and()
.httpBasic(); // Authenticate users with HTTP basic authentication
}
}
Now I try access to /admin. Browser asks me to put username and password and when I do that I will get a access to /admin. Why is that? Why cannot I get a access using jdbcAuthentication()? May you give me some advices?
my guess the mistake is in your query
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name, password"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name, role"
+ "from person where name=?");
jdbcAuthentication expects
for users-by-username-query : username, password and enabled
for authorities-by-username-query username and role
so for you this should work:
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name as username, password, true"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name as username, role"
+ " from person where name=?");