Spring перенаправление безопасности на основе роли

У меня есть следующий файл spring -security.xml: -

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <http auto-config="true">
           <intercept-url pattern="/Freelancer/**" access="ROLE_FREELANCE" />
           <intercept-url pattern="/Client/**" access="ROLE_CLIENT" />
           <intercept-url pattern="/Agency/**" access="ROLE_AGENCY" />
           <intercept-url pattern="/Manager/**" access="ROLE_MANAGER" />
           <intercept-url pattern="/User/**" access="ROLE_USER" />
           <form-login default-target-url="/${role}" login-page="/login.jsp" />
           <logout logout-url="/logout" logout-success-url="/" />
    </http>

    <authentication-manager>
           <authentication-provider>
             <jdbc-user-service data-source-ref="dataSource" 
               users-by-username-query="select user_name,password, enabled from Users where user_name=?"  
               authorities-by-username-query="select u.user_name, u.role from Users u where u.user_name =?"/>                 
           </authentication-provider>
    </authentication-manager>

</beans:beans>  

что я хочу, я хочу перенаправить пользователя в свою рабочую область, например, если клиент будет подключен, то он будет перенаправлен на /Client/index.jsp, если вход в систему Агентства будет перенаправлен в /Agency/index.jsp.

есть ли способ доступа к роли раньше, он будет перенаправлен на свое рабочее пространство в файле spring -security.xml.

<form-login default-target-url="/${role}" login-page="/login.jsp" />

У меня есть синтаксис структуры каталогов для роли.

имеют любую идею.

Ответ 1

Напишите контроллер spring, который будет показывать разные страницы, которые будут показаны на основе роли пользователя. Запишите класс обработчика успешности аутентификации и напишите код, чтобы решить, где перенаправить на основе ролей.

Прежде всего нужно изменить тег <form-login />.

<form-login login-page="/landing" authentication-success-handler-ref="authSuccessHandler" />

<beans:bean id="authSuccessHandler" class="com.package.AuthSuccessHandler" />

Удалите атрибут default-target-url. Пусть auth-обработчик решает, где перенаправить пользователя.

Класс обработчика успеха Auth будет выглядеть следующим образом:

public class AuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
        // Get the role of logged in user
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String role = auth.getAuthorities().toString();

        String targetUrl = "";
        if(role.contains("client")) {
            targetUrl = "/client/index";
        } else if(role.contains("agency")) {
            targetUrl = "/agency/index"
        }
        return targetUrl;
    }
}

Это пример кода. Измените его в соответствии с вашими требованиями.

Ответ 2

Лучше проверять роли с равными в предоставленных полномочиях, содержит может сбой, если несколько роли существуют с одной и той же частью.

Добавьте обработчик успеха проверки подлинности в конфигурацию входа в форму, как показано ниже:

<http auto-config="true">
    <intercept-url pattern="/Freelancer/**" access="ROLE_FREELANCE" />
    <intercept-url pattern="/Client/**" access="ROLE_CLIENT" />
    <intercept-url pattern="/Agency/**" access="ROLE_AGENCY" />
    <intercept-url pattern="/Manager/**" access="ROLE_MANAGER" />
    <intercept-url pattern="/User/**" access="ROLE_USER" />
    <form-login login-page='/login.html'
                authentication-failure-url="/login.html?error=true"
                authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
    <logout logout-url="/logout" logout-success-url="/" />
</http>

И обработчик успеха выглядит следующим образом:

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);
    }

    protected String determineTargetUrl(Authentication authentication) {
        boolean isUser = false;
        boolean isFreelance = false;
        boolean isClient = false;
        boolean isAgency = false;
        boolean isManager = false;
        Collection<? extends GrantedAuthority> authorities
                = authentication.getAuthorities();
        for (GrantedAuthority grantedAuthority : authorities) {
            if (grantedAuthority.getAuthority().equals("ROLE_FREELANCE")) {
                isFreelance = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_CLIENT")) {
                isClient = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_AGENCY")) {
                isAgency = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_MANAGER")) {
                isManager = true;
                break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
                isUser = true;
                break;
            }
        }

        if (isFreelance) {
            return "freelance/homepage.html";
        } else if (isClient) {
            return "client/homepage.html";
        } else if (isAgency) {
            return "agency/homepage.html";
        } else if (isManager) {
            return "manager/homepage.html";
        } else if (isUser) {
            return "user/homepage.html";
        } else {
            throw new IllegalStateException();
        }
    }

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

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }

    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}

Ответ 3

Вы можете использовать решение на основе аннотаций, используя специальный обработчик успеха, подобный этому:

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

@Component
public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {
        String targetUrl = determineTargetUrl(authentication);

        if (response.isCommitted()) {
            System.out.println("Can't redirect");
            return;
        }

        redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    /*
     * This method extracts the roles of currently logged-in user and returns
     * appropriate URL according to his/her role.
     */
    protected String determineTargetUrl(Authentication authentication) {
        String url = "";

        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

        List<String> roles = new ArrayList<String>();

        for (GrantedAuthority a : authorities) {
            roles.add(a.getAuthority());
        }

        if (isDba(roles)) {
            url = "/db";
        } else if (isAdmin(roles)) {
            url = "/admin";
        } else if (isUser(roles)) {
            url = "/home";
        } else {
            url = "/accessDenied";
        }

        return url;
    }

    private boolean isUser(List<String> roles) {
        if (roles.contains("ROLE_USER")) {
            return true;
        }
        return false;
    }

    private boolean isAdmin(List<String> roles) {
        if (roles.contains("ROLE_ADMIN")) {
            return true;
        }
        return false;
    }

    private boolean isDba(List<String> roles) {
        if (roles.contains("ROLE_DBA")) {
            return true;
        }
        return false;
    }

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }

    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }

}

И настройка безопасности как:

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 SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomSuccessHandler customSuccessHandler;

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
        .antMatchers("/", "/home").access("hasRole('USER')")
        .antMatchers("/admin/**").access("hasRole('ADMIN')")
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
        .and().formLogin().loginPage("/login").successHandler(customSuccessHandler)
        .usernameParameter("ssoId").passwordParameter("password")
        .and().csrf()
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");
    }

}