Why permitAll() returns 403 spring security? - java

I have created a method for persisting user details in the database and i also have a controller which is exposed at the endpoint /register. I wanted to make the /register endpoint available to all. I have used spring security and gave permit all for the /register end point.
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsServiceImpl userDetailsService;
#Autowired
public WebSecurityConfiguration(UserDetailsServiceImpl userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests(
request -> request.antMatchers(HttpMethod.POST,"/register").permitAll()
.anyRequest().authenticated()
);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Can someone please explain or help me out why permitAll is not working in my case. As per the code i have written the /register end point should return the user details but it returns 403. The /register endpoint is a rest endpoint which takes the user details as input and return the user details as output once the detal is persisted to the database.
#Slf4j
#RestController
public class RegistrationController {
private final UserDetailsServiceImpl userDetailsService;
#Autowired
public RegistrationController(UserDetailsServiceImpl userDetailsService) {
this.userDetailsService = userDetailsService;
}
#PostMapping(value = "/register")
public ResponseEntity<Users> registerNewUser(#Valid #RequestBody Users users) throws EmailAlreadyExistsException {
Users usersDetails = userDetailsService.processRegistration(users);
log.info("{}, Information: Successfully persisted new user",this.getClass().getSimpleName());
return new ResponseEntity<>(usersDetails,HttpStatus.OK);
}
}

I guess you are calling the url via curl or postman. You must then disable CSRF or use a GET mapping instead.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests(
request -> request.antMatchers(HttpMethod.POST,"/register").permitAll()
.anyRequest().authenticated()
);
}

Related

Spring Security: Multiple Basic Auth with different user stores without WebSecurityConfigurerAdapter

I am currently refactoring the security configuration removing WebSecurityConfigurerAdapter and am currently stuck on a config using two Basic Auth configurations with different user stores on different paths.
Current configuration looks like this and works fine:
#EnableWebSecurity
public class SecurityConfig {
#Order(1)
#Configuration
public static class BasicSpecialAuth extends WebSecurityConfigurerAdapter {
// some code
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// some code
auth.inMemoryAuthentication().withUser(specialUser.getId()).password(passwordEncoder().encode(specialUser.getPassword())).roles("SPECIALROLE");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.antMatcher("/very-special-path/**")
//. more code
.authorizeRequests(r -> r
.anyRequest().authenticated());
}
}
#Order(2)
#Configuration
public static class BasicAppAuth extends WebSecurityConfigurerAdapter {
// some code
#Bean
public CustomUserDetailsService customUserDetailsService() {
return new CustomUserDetailsService(userRepository);
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService())
.passwordEncoder(encoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
//. more code
.authorizeRequests(auth -> auth
.anyRequest().authenticated());
}
}
}
As can be seen, /very-special-path uses InMemoryAuthentication set up at start by configuration.
All other paths should be authenticated using users from local database. Due to possible duplicates on usernames I am not able to use the database for /very-special-path users too. Requirement is to have these separated.
Following documentation it was quite simple to change this on our apps providing Basic Auth and JWT Auth on different path. But with both using Basic Auth and different user stores, I have no idea how to set up configuration properly.
Any help would be appreciated.
Edit, the current config:
#Configuration
public class SecurityConfig {
// some code
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public UserDetailsService customUserDetailsService() {
return new CustomUserDetailsService(userRepository);
}
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsService() {
// more code
UserDetails healthUser = User.withUsername(specialUser.getId())
.password(passwordEncoder().encode(specialUser.getPassword()))
.roles("SPECIALROLE")
.build();
return new InMemoryUserDetailsManager(healthUser);
}
#Bean
#Order(1)
public SecurityFilterChain specialFilterChain(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.antMatcher("/very-special-path/**")
.authorizeRequests(auth -> auth
.anyRequest().authenticated());
return http.build();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests(auth -> auth
.anyRequest().authenticated());
return http.build();
}
}
The app starts without any Warning or Error.
Both chains are mentioned in the log:
o.s.s.web.DefaultSecurityFilterChain : Will secure any request with ..
o.s.s.web.DefaultSecurityFilterChain : Will secure Ant [pattern='/very-special-path/**'] with ..
But authentication does not work. Checked for different endpoints and with different users. Every request gets an 401.
This config misses the assignment of the UserDetails to the specific filter chain. Is there a way to do so?
Based on the extra information you provided, there are only a couple of tweaks needed to get your configuration working. Take a look at this blog post that details common patterns for replacing WebSecurityConfigurerAdapter with the component-based approach, specifically the local AuthenticationManager.
For the special/health user, you can manually construct a local authentication manager so as not to collide with the global one declared as an #Bean. Here's a full example:
#EnableWebSecurity
public class SecurityConfig {
// ...
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public UserDetailsService customUserDetailsService() {
return new CustomUserDetailsService(userRepository);
}
#Bean
#Order(1)
public SecurityFilterChain specialFilterChain(HttpSecurity http, PasswordEncoder passwordEncoder) throws Exception {
http
.mvcMatcher("/very-special-path/**")
.authorizeRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.authenticationManager(specialAuthenticationManager(passwordEncoder));
return http.build();
}
private AuthenticationManager specialAuthenticationManager(PasswordEncoder passwordEncoder) {
UserDetailsService userDetailsService = specialUserDetailsService(passwordEncoder);
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setPasswordEncoder(passwordEncoder);
authenticationProvider.setUserDetailsService(userDetailsService);
return new ProviderManager(authenticationProvider);
}
private UserDetailsService specialUserDetailsService(PasswordEncoder passwordEncoder) {
UserDetails specialUser = User.withUsername("specialuser")
.password(passwordEncoder.encode("specialpassword"))
.roles("SPECIALROLE")
.build();
return new InMemoryUserDetailsManager(specialUser);
}
#Bean
#Order(2)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}

403 forbidden in Spring Security with Custom UserDetailsService only [duplicate]

This question already has answers here:
Springboot Security hasRole not working
(3 answers)
Closed 1 year ago.
I have following files in spring boot project for Spring Security. When I use inMemoryAuthentication it works but when I go with custom UserDetailsService it doesn't work. Custom UserDetailsService class gets called but still it gives 403 (when I am trying to access /user) but it works for open urls (/usr).
import org.springframework.security.core.userdetails.User
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//not using parameter which is being passed as trying to figure out the problem first.
UserDetails user = User.withUsername("abc").password("abc").authorities("ADMIN").build();
return user;
}
}
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
// auth.inMemoryAuthentication().withUser("abc").password("abc").roles("ADMIN");
}
#Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/user").hasRole("ADMIN")
.antMatchers("/").permitAll()
.and().formLogin();
}
}
#RestController
#RequestMapping("/api")
public class UserController {
#GetMapping("/usr")
public ResponseEntity<String> getOpenResponse() {
return ResponseEntity.ok("You are accessing open url");
}
#GetMapping("/user")
public ResponseEntity<String> getSecuredResponse() {
return ResponseEntity.ok("You are accessing secured path");
}
}
What am I doing wrong here? Am I missing something?
The problem is here :
UserDetails user = User.withUsername("abc").password("abc").authorities("ADMIN").build();
You set your user’s authority to "ADMIN", but in SecurityConfig class you expect the user to have a role "ADMIN", which is, in fact, a shortcut for an authority of "ROLE_ADMIN" :
http.authorizeRequests()
.antMatchers("/api/user").hasRole("ADMIN")
To solve the problem you should define the user’s role :
User.withUsername("abc").password("abc").roles("ADMIN")

Spring Security add a custom filter chain just for for Registration API [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm building a Rest application and I need to apply a filter(this filters will do the validation of the credentials like email is valid, the username is not already toked, the password is strong and match confirmationPassword).
I want to apply this chain just for Registration and no other filter (like check if you are authenticated)
I have something like this in spring securityConfiguration
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final BCryptPasswordEncoder passwordEncoder;
private final UserServiceImplementation serviceImplementation;
private final JwtConfiguration jwtConfiguration;
#Autowired
public SecurityConfiguration(UserServiceImplementation serviceImplementation, BCryptPasswordEncoder passwordEncoder, JwtConfiguration jwtConfiguration) {
this.serviceImplementation = serviceImplementation;
this.passwordEncoder = passwordEncoder;
this.jwtConfiguration = jwtConfiguration;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfiguration))
.addFilterAfter(new JwtTokenVerifier(jwtConfiguration), JwtUsernameAndPasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest()
.authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(daoAuthenticationProvider());
}
#Override
public void configure(WebSecurity web) {
web.debug(true);
web.ignoring().antMatchers(HttpMethod.GET, "/register/**");
web.ignoring().antMatchers(HttpMethod.POST, "/register/**");
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder);
provider.setUserDetailsService(serviceImplementation);
return provider;
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
}
I will appreciate any input and any suggestions from the community!
You can create a POST mapping controller method to handle validation of registration. Firstly you should permit url of registration as follows in your SpringSecurityConfig.
#Autowired
private UserRepository userRepository;
#Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return new CustomUserDetailsServiceImpl(userRepository);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/v1/user/register").permitAll();
}
In UserController:
#RestController
#RequestMapping("/api/v1/user")
public class UserController {
#Autowired
private CustomUserDetailsServiceImpl userDetailsService;
#Autowired
public UserController(CustomUserDetailsServiceImpl userDetailsService) {
this.userDetailsService = userDetailsService;
}
#PostMapping(value = "/register")
public User register(#RequestBody User user) {
return userDetailsService.save(user);
}
}
UserRepository:
public interface UserRepository extends JpaRepository<User, String> {
User findByUsername(String username);
}
In CustomUserDetailsServiceImpl: You can filter validation in this implementation (email is valid, the username is not already toked, the password is strong and match confirmationPassword)
public User save(User user){
if(StringUtils.isEmpty(user.getUsername())) {
throw ExceptionFactory.getApiError(ExceptionEnum.BAD_REQUEST, "username");
}
if(StringUtils.isEmpty(user.getPassword())) {
throw ExceptionFactory.getApiError(ExceptionEnum.BAD_REQUEST, "password");
}
User registeredUser = new User();
registeredUser.setUsername(user.getUsername());
registeredUser.setPassword(passwordEncoder.encode(user.getPassword()));
registeredUser.setEnabled(true);
registeredUser.setRoles(Arrays.asList(new Role(RoleEnum.USER.getRole())));
return userRepository.save(registeredUser);
}

Multiple WebSecurityConfigurerAdapters: JWT authentication and form login in spring security

I have spring boot app with thymeleaf. I am using spring security formLogin method for security and now I need to add JWT for only some APIs.
#EnableWebSecurity
public class SecurityConfigurations {
#Autowired
UserDetailsServiceImpl userDetails;
#Bean
DaoAuthenticationProvider provider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(encoder());
provider.setUserDetailsService(userDetails);
return provider;
}
#Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Configuration
#Order(1)
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private JwtRequestFilter jwtRequestFilter;
#Autowired
DaoAuthenticationProvider provider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(provider);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/api/user/authenticate").permitAll()
.antMatchers("/api/user/**").hasRole("USER")
.and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
#Configuration
public static class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
DaoAuthenticationProvider provider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(provider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
.loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.invalidateHttpSession(false).and().csrf().disable().cors();
}
}
}
by doing this JWT is working fine as just I need but the formlogin has stopped and calling "/signInProcess" now give 404:
NOTE: if I change the order and make formLogin #order(1) it works again but of course will not work.
Also I tried to combine them both like this now it is both works fine but the problem with exception handling if the JWT authentication error will return formlogin thymeleaf error page :
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
.antMatchers("/api/user/authenticate").permitAll()
.antMatchers("/api/user/**").hasRole("USER")
.anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
.loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.invalidateHttpSession(false).and().csrf().disable().cors();
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
any suggestions to make this work. thank you.
Your WebSecurityConfigurerAdapters will process the incoming requests in order.
Since JWTSecurityConfig is annotated with #Order(1) it will process the requests first.
You have not specified a antMatcher for this Adapter, so it will match all requests.
This means that a request will never reach FormLoginConfigurationAdapter, since JWTSecurityConfig matches them all.
If you want JWTSecurityConfig to only apply to certain requests, you can specify an antMatcher in your security configuration.
Below is an example:
#EnableWebSecurity
public class SecurityConfigurations {
#Configuration
#Order(1)
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers(matchers -> matchers
.antMatchers("/api/**") // apply JWTSecurityConfig to requests matching "/api/**"
)
.authorizeRequests(authz -> authz
.anyRequest().authenticated()
)
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
#Configuration
public class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authz -> authz
.anyRequest().authenticated()
)
.formLogin();
}
}
}
For more details on multiple WebSecurityConfigurerAdapter, you can see the multiple HttpSecurity section in the Spring Security reference docs.
For more details on the difference between authorizeRequests() and requestMatchers(), you can see this Stack Overflow question.

How to configure multiple HttpSecurity with UserDetailsService using spring boot security?

I'm working on with spring boot security layer to authenticate and authorize the user.Now, i would like to do some sample app using multi http security configuration.I have the scenario like there will be two login pages with different URL mappings("/managementLogin","/othersLogin").
I can understood how to configure multi httpsecurity configs but i need to validate the users from two tables.If the management users loggedIn i need to validate the user from management table through DAO layer using UserDetailsService else if any other users loggedIn i need to validate from other_users table.
Could anybody help me to know how to configure the multi http config and dao layer using UserDetailsService with spring boot security ?
Here is my basic code snippet,
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
#Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// for testing authentication purpose using inMemory db
/*
* auth.inMemoryAuthentication().withUser("user").password("user").roles
* ("USER").and().withUser("admin") .password("admin").roles("ADMIN");
*/
// Dao based authentication
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home").permitAll();
http.authorizeRequests().antMatchers("/rest/**").authenticated();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.logout().logoutSuccessUrl("/");
// CSRF tokens handling
http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/registerUser","/register.html");
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
TIA..,
Implement a custom UserDetailsService like this:
#Service
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserDaoTableOne userDaoTableOne;
#Autowired
private UserDaoTableTwo userDaoTableTwo;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails user = userDaoTableOne.find(username);
if(user == null){
user = userDaoTableTwo.find(username);
}
if (user == null) {
throw new UsernameNotFoundException(String.format("Username '%s' not found", username));
}
return user;
}
}
Implement two DaoAuthenticationProvider with his own UserDetailsService and inject both providers to the authenticationManager.
I don't know what is the requisite for two distinct login endpoints but at first I think is a bad idea.
You can create different Authentication objects an let the AuthenticationManager choose the correct AuthenticationProvider based in the supports method.
Indeed you will need to use, two user detail services. But, that wont be enough. I suggest you to create another ApplicationSecurity2 class with different order.
Spring security is built on an ordered list of filter chains.
see the answer given here by Dave Sayer. Then you can handle different urls, as you want.
in my case I checked into two repositories, Below an exemple that I use:
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AbstractUser user;
try {
user = clientRepository.findByUsername(username);
}
catch (Exception userException) {
try {
user = adminRepository.findByUsername(username);
}
catch (Exception adminException) {
throw new UsernameNotFoundException("No user present with username : " + username);
}
}
return user;
}
I have to handle around same issue , i have autowired httprequest class in userdetail service and get request params type and drive my logic based on that.
you can directly solve the issue as the recommended solutions, but you can create a simple trick to define two different UserDetailsService as here I have two user one as a normal user and another as an editor :
editor
#Log4j2
#RequiredArgsConstructor
#Service
public class EditorService implements UserDetailsService {
private final EditorRepository editorRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)){
throw new UsernameNotFoundException("null value");
}
Optional<Editor> editor = editorRepository.findByUsername(username);
if(editor.isPresent()){
log.info("created under editor service: " + editor.get());
return editor.get();
}
throw new UsernameNotFoundException("does not exists");
}
}
user
#Log4j2
#RequiredArgsConstructor
#Service
public class UserService implements UserDetailsService {
private final UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)){
throw new UsernameNotFoundException("null");
}
Optional<User> user = userRepository.findByUsername(username);
if(user.isPresent()){
log.info("cretaed under User service : " + user.get());
return user.get();
}
throw new UsernameNotFoundException("does not exists");
}
}
then on the configurations side, we can use of spring order mechanism :
user config :
#EnableWebSecurity
#Configuration
#RequiredArgsConstructor
#Order(1)
public class UserWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/user/**")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(10);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userService).passwordEncoder(passwordEncoder());
}
}
Editor config :
#EnableWebSecurity
#Configuration
#RequiredArgsConstructor
public class EditorWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final EditorService editorService;
#Lazy
private final PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http // all other requests handled here
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.editorService).passwordEncoder(passwordEncoder);
}
}

Categories

Resources