Я страдаю за обработку нескольких входов.
Я много об этом искал, и ни один из ответов там не работает.
Я написал две обработки входа: одну для администратора, а другую для обычного пользователя.
И также написал каждый обработчик успеха и неудачи, но обработчики всегда работают с последним в конфигурации @order(2)
, хотя я запрашиваю /admin
.
Мои проблемы:
Я могу войти, но обработчик успеха всегда запускается как последний в @order(2)
.
Обработчик ошибки запускается, но также и как последний, независимо от того, что URL, который я запрашиваю, и он выдает ошибку 404 (я вижу, что он идет на правильном контроллере во время отладки). Может быть, плитки не работают при сбое?
Вот мой конфиг безопасности:
@Configuration
@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private UsersServiceImpl usersService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/css/**",
"/js/**",
"/img/**",
"/font/**",
"/html/**",
"/jusoPopup",
"favicon.ico"
);
}
@Configuration
@Order(1)
@NoArgsConstructor
public static class AdminConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/admin/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/admin/login")
.defaultSuccessUrl("/admin")
.failureHandler(adminFailureHandler())
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.csrf().disable();
}
@Bean
public AuthenticationSuccessHandler adminSuccessHandler() {
return new CustomLoginSuccessHandler("/admin");
}
@Bean
public AuthenticationFailureHandler adminFailureHandler() {
return new CustomLoginFailureHandler("/admin/login?error=true");
}
}
@Configuration
@Order(2)
@NoArgsConstructor
public static class NormalConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/Ticketing/**", "/**/write").hasRole("MEMBER")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler())
.failureHandler(failureHandler())
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.headers()
.frameOptions().sameOrigin()
.and()
.csrf().disable();
}
@Bean
public AuthenticationSuccessHandler successHandler() {
return new CustomLoginSuccessHandler("/");
}
@Bean
public AuthenticationFailureHandler failureHandler() {
return new CustomLoginFailureHandler("/login?error=true");
}
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usersService).passwordEncoder(passwordEncoder());
}
}
class CustomLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
public CustomLoginSuccessHandler(String defaultTargetUrl) {
setDefaultTargetUrl(defaultTargetUrl);
}
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication
) throws ServletException, IOException {
HttpSession session = request.getSession();
if (session != null) {
String redirectUrl = (String) session.getAttribute("prevPage");
if (redirectUrl != null) {
session.removeAttribute("prevPage");
getRedirectStrategy().sendRedirect(request, response, redirectUrl);
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
@Getter
@Setter
@AllArgsConstructor
class CustomLoginFailureHandler implements AuthenticationFailureHandler {
private String defaultFailureUrl;
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception
) throws IOException, ServletException {
String errorMessage = "some error message";
request.setAttribute("errorMessage", errorMessage);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
}
}
Трудно найти работающий ресурс для обработки нескольких входов. если вы, ребята, знаете хороший ресурс об этом, пожалуйста, дайте мне знать.
Я надеюсь, что это ошибка моего кода, чтобы мне не пришлось менять структуру приложения.
Я прочитал какое-то руководство по Baeldung и весенние документы по безопасности Вот моя отредактированная конфигурация:
@EnableWebSecurity
public class SecurityConfig{
@NoArgsConstructor
@Configuration
@Order(1)
public static class AdminConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/admin/**")
.authorizeRequests().anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/admin/login")
.defaultSuccessUrl("/admin")
.failureHandler(adminFailureHandler())
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.csrf().disable();
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint(){
BasicAuthenticationEntryPoint entryPoint =
new BasicAuthenticationEntryPoint();
entryPoint.setRealmName("admin realm");
return entryPoint;
}
@Bean
public AuthenticationFailureHandler adminFailureHandler() {
return new CustomLoginFailureHandler("/admin/login");
}
}
@AllArgsConstructor
@Configuration
public static class NormalConfigurationAdapter extends WebSecurityConfigurerAdapter {
private UsersServiceImpl usersService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(
"/css/**",
"/js/**",
"/img/**",
"/font/**",
"/html/**",
"/jusoPopup",
"favicon.ico"
);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/Ticketing/**", "**/write")
.hasRole("MEMBER")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler())
.failureHandler(failureHandler())
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.and()
.headers().frameOptions().sameOrigin()
.and()
.csrf().disable();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usersService).passwordEncoder(passwordEncoder());
}
@Bean
public AuthenticationSuccessHandler successHandler() {
return new CustomLoginSuccessHandler("/");
}
@Bean
public AuthenticationFailureHandler failureHandler() {
return new CustomLoginFailureHandler("/login");
}
}
}
class CustomLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
public CustomLoginSuccessHandler(String defaultTargetUrl) {
setDefaultTargetUrl(defaultTargetUrl);
}
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication
) throws ServletException, IOException {
HttpSession session = request.getSession();
if (session != null) {
String redirectUrl = (String) session.getAttribute("prevPage");
if (redirectUrl != null) {
session.removeAttribute("prevPage");
getRedirectStrategy().sendRedirect(request, response, redirectUrl);
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
@Getter
@Setter
@AllArgsConstructor
class CustomLoginFailureHandler implements AuthenticationFailureHandler {
private String defaultFailureUrl;
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception
) throws IOException, ServletException {
String errorMessage = "Error";
request.setAttribute("errorMessage", errorMessage);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
}
}
Это выглядит более организованно, чем раньше, я думаю, но все еще имеет ту же проблему ... также читайте о AuthenticationEntryPoint, но не уверен, что это подходит в моем случае