Как вернуть HTTP 403 после успешной аутентификации, но неудачной авторизации?JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Как вернуть HTTP 403 после успешной аутентификации, но неудачной авторизации?

Сообщение Anonymous »

У меня есть приложение Spring Boot, которое также использует Spring Security. Я хочу проверить, есть ли у пользователя доступ для входа в приложение, но это должно быть после аутентификации. Суть в том, что при входе пользователь выбирает проект, к которому ему необходимо подключиться. Пользователю может быть разрешено подключение к одному проекту, но не разрешено подключение к другому проекту. Однако, если пользователь вводит неверные учетные данные, сначала должно отображаться сообщение о неверных учетных данных, даже если у пользователя нет прав на вход в выбранный проект. По этой причине проверка прав на проект должна быть после аутентификации.
Это мой класс SecurityConfig:

Код: Выделить всё

package org.aze.accountingprogram.config;

import org.aze.accountingprogram.models.CurrentUser;
import org.aze.accountingprogram.models.PermissionAliasConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
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.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/lib/**").permitAll().anyRequest().fullyAuthenticated()
.and()
.formLogin().successHandler(successHandler()).loginPage("/login").permitAll()
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler())
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();

http.csrf().disable();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new Md5PasswordEncoder());
}

private AccessDeniedHandler accessDeniedHandler() {
return (request, response, e) -> {
logger.debug("Returning HTTP 403 FORBIDDEN with message: \"{}\"", e.getMessage());
response.sendError(HttpStatus.FORBIDDEN.value(), e.getMessage());
};
}

private AuthenticationSuccessHandler successHandler() {
return new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
CurrentUser user = (CurrentUser) authentication.getPrincipal();
if (!user.hasAccessRight(PermissionAliasConstants.LOGIN)) {
throw new AccessDeniedException(String.format("User \"%s\" is not authorized to login \"%s\"  project", user.getUsername(), user.getProject().getName()));
}
}
};
}

}
реализация UserDetailsService:

Код: Выделить всё

package org.aze.accountingprogram.serviceimpl;

import org.aze.accountingprogram.common.Constants;
import org.aze.accountingprogram.exceptions.DataNotFoundException;
import org.aze.accountingprogram.models.AccessRightsPermission;
import org.aze.accountingprogram.models.CurrentUser;
import org.aze.accountingprogram.models.Project;
import org.aze.accountingprogram.models.User;
import org.aze.accountingprogram.service.AccessRightsService;
import org.aze.accountingprogram.service.ProjectService;
import org.aze.accountingprogram.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserService userService;

@Autowired
private ProjectService projectService;

@Autowired
private AccessRightsService accessRightsService;

@Autowired
private HttpServletRequest request;

private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user;
Project project;
final String projectId = request.getParameter(Constants.SESSION_PROJECT_ID);
logger.debug("Username: {}, projectId: {}", username, projectId);

try {
user = userService.getUserByUsername(username);
} catch (DataNotFoundException e) {
throw new UsernameNotFoundException(e.getMessage(), e);
}

// Value of projectId is from combo box which is filled from table of projects
// That is why there is no probability that the project will not be found
project = projectService.getProjectById(Integer.valueOf(projectId));

// User can have different rights for different projects
List accessRights = accessRightsService.getAccessRightsByProject(user.getId(), project.getId());
Set authorities = new HashSet(accessRights.size());
authorities.addAll(accessRights.stream().map(right -> new SimpleGrantedAuthority(right.getAlias())).collect(Collectors.toList()));

final CurrentUser currentUser = new CurrentUser(user, project, authorities);

// If to check LOGIN access right to project here, and user entered right credentials
// then user will see message about invalid credentials.
// .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler()) at SecurityConfig is not working in this case
//        if (!currentUser.hasAccessRight(PermissionAliasConstants.LOGIN)) {
//            throw new AccessDeniedException(String.format("User \"%s\" is not authorized to login \"%s\" project", user.getUsername(), project.getName()));
//        }

logger.info("Logged in user: {}", currentUser);
return currentUser;
}
}
и LoginController

Код: Выделить всё

package org.aze.accountingprogram.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import java.util.Optional;

@Controller
public class LoginController {

@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView getLoginPage(@RequestParam Optional  error) {
return new ModelAndView("login", "error", error);
}

}

Код: Выделить всё

successHandler()
работает, и приложение выдает исключение AccessDeniedException, если у пользователя нет права доступа для входа в проект. Но accessDeniedHandler() не работает и не отправляет HTTP 403. Вместо этого я получаю HTTP 500.
Как вернуть ответ с HTTP 403 и сообщением об исключении (например, «Пользователь «tural» не имеет прав для входа в проект «AZB») и обработки его в LoginController (с использованием @ResponseStatus(HttpStatus.FORBIDDEN) или @ExceptionHandler)?

Подробнее здесь: https://stackoverflow.com/questions/364 ... ul-authori
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение