Spring security + spring webflow如何在带有用户角色的成功登录页面后重定向?

时间:2016-05-08 13:37:12

标签: java spring spring-mvc redirect spring-webflow

在春季框架初学者,我成功登录后我的重定向应用程序有问题

  1. 我在网上发布此视频以开发我的应用https://www.youtube.com/watch?v=94OvXuwqnGc
  2. 当我想在登录后重定向我的应用程序时,我发现了一个问题: 如果用户有" ROLE_ADMIN"如果用户有" ROLE_USER"他们应该重定向到accountAdmin.xhtml。他们应该重定向到accountUser.xtml;但他们将所有用户重定向到accountAdmin.xhtml
  3. 我的应用程序有一个结构: app structure

    这是我的main-flow.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <flow xmlns="http://www.springframework.org/schema/webflow"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/webflow
            http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
    
        <var name="user" class="com.ismart.itubibe.entities.UserEntity"/>
    
        <view-state id="welcome" view="welcome.xhtml" model="user">
            <transition on="newUser" to="signUp"/>
            <transition on="signIn" to="finish">
                <evaluate expression="userAuthenticationProviderService.processUserAuthentication(user)"/>
            </transition>
        </view-state>
    
        <view-state id="signUp" view="signUp.xhtml" model="user">
            <transition on="backToSignIn" to="welcome"/>
            <transition on="signUp" to="authentication">
                <evaluate expression="userServices.createUser(user)"/>
            </transition>
        </view-state>
    
        <action-state id="authentication">
            <evaluate expression="userAuthenticationProviderService.processUserAuthentication(user)"/>
            <transition on="yes" to="finish" />
            <transition on="no" to="welcome" />
        </action-state>
    
        <end-state id="finish" view="externalRedirect:account" />
    
    </flow>
    

    我的security-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:security="http://www.springframework.org/schema/security"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                http://www.springframework.org/schema/security
                http://www.springframework.org/schema/security/spring-security.xsd">
    
        <security:http auto-config="true">
    
            <security:form-login login-page="/app/main" default-target-url="/app/account" authentication-success-handler-ref="customAuthenticationSuccessHandler" />
            <security:logout logout-url="/app/logout" logout-success-url="/app/main" />
        </security:http>
    
        <security:authentication-manager>
            <security:authentication-provider user-service-ref="userServices">
                <security:password-encoder hash="md5" />
            </security:authentication-provider>
        </security:authentication-manager>
        <bean id="customAuthenticationSuccessHandler" class="com.ismart.test.services.impl.CustomAuthenticationSuccessHandler"/>
        <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
            <property name="userDetailsService" ref="userServices" />
            <property name="hideUserNotFoundExceptions" value="false" />
        </bean>
    
        <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
            <constructor-arg>
                <ref bean="daoAuthenticationProvider" />
            </constructor-arg>
        </bean>
    
    </beans>
    

    我的account-flow.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <flow xmlns="http://www.springframework.org/schema/webflow"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/webflow
            http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
    
        <secured attributes="ROLE_USER, ROLE_ADMIN" match="any"/>
    
        <view-state id="admin" view="accountAdmin.xhtml">
        </view-state>
    
        <view-state id="user" view="accountUser.xhtml">
        </view-state>
    
    </flow>
    

    我的加载用户详细信息方法:

    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
    
                    UserEntity user = userDao.loadUserByUserName(userName);
    
                    if(user == null){
                        throw new UsernameNotFoundException(String.format("Etulisateur introuvable '%s'", userName)); 
                    }
    
                    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    
                    authorities.add(new SimpleGrantedAuthority(user.getUserType()));
    
                    User userDetails = new User(user.getUserName(), user.getPassWord(), authorities);
    
                    return userDetails;
                }
    

    身份验证方法

    public boolean processUserAuthentication(UserEntity user) {
            try {
                Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassWord());
                Authentication result = authenticationManager.authenticate(request);
                SecurityContextHolder.getContext().setAuthentication(result);
                return true;
            } catch (AuthenticationException e) {
    
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), "Sorry!!"));
                return false;
            }
        }
    

    我的CustomAuthenticationSuccessHandler:

    public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
        private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request,
                HttpServletResponse response, Authentication authentication) throws IOException,
                ServletException {
             Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    
            /*Set target URL to redirect*/
            String targetUrl = determineTargetUrl(auth); 
            redirectStrategy.sendRedirect(request, response, targetUrl);
        }
    
        protected String determineTargetUrl(Authentication authentication) {
            Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
            if (authorities.contains("ROLE_ADMIN")) {
                return "/accountAdmin.xhtml";
            } else if (authorities.contains("ROLE_USER")) {
                return "/accountUser.xhtml";
            } else {
                throw new IllegalStateException();
            }
        }
    
        public RedirectStrategy getRedirectStrategy() {
            return redirectStrategy;
        }
    
        public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
            this.redirectStrategy = redirectStrategy;
        }
    }
    

    和我的web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        <display-name>iTubibe</display-name>
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
        </context-param>
    
        <context-param>
            <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
            <param-value>.xhtml</param-value>
        </context-param>
    
        <context-param>
            <param-name>facelets.DEVELOPMENT</param-name>
            <param-value>true</param-value>
        </context-param>
    
        <context-param>
            <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
            <param-value>1</param-value>
        </context-param>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>Resources Servlet</servlet-name>
            <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
            <load-on-startup>0</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>Resources Servlet</servlet-name>
            <url-pattern>/resources/*</url-pattern>
        </servlet-mapping>
    
        <servlet>
            <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value></param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
            <url-pattern>/app/*</url-pattern>
        </servlet-mapping>
    
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.jsf</url-pattern>
        </servlet-mapping>
    
        <filter>
            <filter-name>charEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
    
        <filter-mapping>
            <filter-name>charEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <context-param>
            <param-name>primefaces.THEME</param-name>
            <param-value>excite-bike</param-value>
        </context-param>
        <context-param>
            <param-name>primefaces.FONT_AWESOME</param-name>
            <param-value>true</param-value>
        </context-param>
        <!-- Spring security filters -->
        <filter>
            <filter-name>springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>springSecurityFilterChain</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>
    

    你能告诉我我的错误在哪里,以及我如何处理所有

    的问题

1 个答案:

答案 0 :(得分:1)

您的帐户流程:

<secured attributes="ROLE_USER, ROLE_ADMIN" match="any"/>

<view-state id="admin" view="accountAdmin.xhtml">
</view-state>

<view-state id="user" view="accountUser.xhtml">
</view-state>

没有任何条件。对于ROLE_USER和ROLE_ADMIN,将在调用流时呈现第一个视图状态“admin”。

您需要的是从决策状态开始:

<secured attributes="ROLE_USER, ROLE_ADMIN" match="any"/>

<decision-state id="userOrAdmin">
    <if test="userAuthenticationProviderService.isAdmin(currentUser)" then="admin" else="user"/>
</decision-state>

<view-state id="admin" view="accountAdmin.xhtml">
</view-state>

<view-state id="user" view="accountUser.xhtml">
</view-state>

您需要创建userAuthenticationProviderService.isAdmin(principal)方法来检查用户是否具有管理员角色。我认为你不能直接在流程中做到这一点。