Пренасочване към различни страници след влизане с Spring Security

1. Общ преглед

Често изискване за уеб приложение е да пренасочва различни видове потребители към различни страници след влизане . Пример за това би било пренасочването на стандартни потребители към /homepage.html страница и администраторски потребители към страница /console.html например.

Тази статия ще покаже как бързо и безопасно да приложите този механизъм с помощта на Spring Security. Статията се основава и на урока Spring MVC, който се занимава с настройка на основните MVC неща, необходими за проекта.

2. Пролетната конфигурация на защитата

Spring Security осигурява компонент, който носи пряката отговорност да реши какво да прави след успешно удостоверяване - AuthenticationSuccessHandler .

2.1. Основна конфигурация

Нека първо конфигурираме основен клас @Configuration и @Service :

@Configuration @EnableWebSecurity public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // ... endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .defaultSuccessUrl("/homepage.html", true) // ... other configuration } }

Частта от тази конфигурация, върху която да се съсредоточите, е методът defaultSuccessUrl () . След успешно влизане всеки потребител ще бъде пренасочен към homepage.html .

Освен това трябва да конфигурираме потребителите и техните роли. За целите на тази статия ще приложим проста UserDetailService с двама потребители, всеки от които с една-единствена роля. За повече информация по тази тема прочетете нашата статия Пролетна сигурност - роли и привилегии.

@Service public class MyUserDetailsService implements UserDetailsService { private Map roles = new HashMap(); @PostConstruct public void init() { roles.put("admin2", new User("admin", "{noop}admin1", getAuthority("ROLE_ADMIN"))); roles.put("user2", new User("user", "{noop}user1", getAuthority("ROLE_USER"))); } @Override public UserDetails loadUserByUsername(String username) { return roles.get(username); } private List getAuthority(String role) { return Collections.singletonList(new SimpleGrantedAuthority(role)); } } 

Също така имайте предвид, че в този прост пример няма да използваме кодер на парола, поради което паролите са с префикс {noop} .

2.2. Добавяне на персонализирания манипулатор за успех

Сега имаме двама потребители с двете различни роли: потребител и администратор . След успешно влизане и двете ще бъдат пренасочени към hompeage.html . Нека да разгледаме как можем да имаме различно пренасочване въз основа на ролята на потребителя.

Първо, трябва да определим персонализиран манипулатор на успех като боб:

@Bean public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){ return new MySimpleUrlAuthenticationSuccessHandler(); } 

И след това заменете извикването defaultSuccessUrl с метода successHandler , който приема нашия потребителски манипулатор за успех като параметър:

@Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .successHandler(myAuthenticationSuccessHandler()) // other configuration } 

2.3. XML конфигурация

Преди да разгледаме изпълнението на нашия потребителски манипулатор за успех, нека разгледаме и еквивалентната XML конфигурация:

3. Персонализираният манипулатор за успех на удостоверяване

Освен интерфейса AuthenticationSuccessHandler , Spring предлага и разумно подразбиране за този стратегически компонент - AbstractAuthenticationTargetUrlRequestHandler и проста реализация - SimpleUrlAuthenticationSuccessHandler . Обикновено тези реализации ще определят URL след влизане и ще извършват пренасочване към този URL.

Макар и донякъде гъвкав, механизмът за определяне на този целеви URL не позволява определянето да се извършва програмно - така че ще внедрим интерфейса и ще осигурим персонализирана реализация на манипулатора на успеха. Това изпълнение ще определи URL адреса за пренасочване на потребителя след влизане въз основа на ролята на потребителя.

На първо място, трябва да заменим метода onAuthenticationSuccess :

public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { protected Log logger = LogFactory.getLog(this.getClass()); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { handle(request, response, authentication); clearAuthenticationAttributes(request); } 

Нашият персонализиран метод извиква два помощни метода:

protected void handle( HttpServletRequest request, HttpServletResponse response, Authentication authentication ) throws IOException { String targetUrl = determineTargetUrl(authentication); if (response.isCommitted()) { logger.debug( "Response has already been committed. Unable to redirect to " + targetUrl); return; } redirectStrategy.sendRedirect(request, response, targetUrl); } 

Когато следният метод върши действителната работа и картографира потребителя към целевия URL адрес:

protected String determineTargetUrl(final Authentication authentication) { Map roleTargetUrlMap = new HashMap(); roleTargetUrlMap.put("ROLE_USER", "/homepage.html"); roleTargetUrlMap.put("ROLE_ADMIN", "/console.html"); final Collection authorities = authentication.getAuthorities(); for (final GrantedAuthority grantedAuthority : authorities) { String authorityName = grantedAuthority.getAuthority(); if(roleTargetUrlMap.containsKey(authorityName)) { return roleTargetUrlMap.get(authorityName); } } throw new IllegalStateException(); } 

Имайте предвид, че този метод ще върне картографирания URL адрес за първата роля, която потребителят има. Така че, ако потребителят има няколко роли, нанесеният URL адрес ще бъде този, който съответства на първата роля, дадена в колекцията на органите .

protected void clearAuthenticationAttributes(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); }

В determineTargetUrl - което е в основата на стратегията - просто гледа типа потребители (определя от органа) и взима целевия URL адрес на базата на тази роля .

Така че администраторски потребител - определен от ROLE_ADMIN органа - ще бъде пренасочен към страницата на конзолата след влизане, докато стандартният потребител - както е определен от ROLE_USER - ще бъде пренасочен към началната страница.

4. Заключение

Както винаги, кодът, представен в тази статия, е достъпен в GitHub. Това е проект, базиран на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.