如何自定义Spring Security交换机用户?

时间:2015-03-06 15:26:16

标签: spring-security

我已在我的网络应用中启用了切换用户。现在,我想在移动应用上做类似的事情,但目标网址应该不同。

在网络应用中,目标网址为/account(返回jsp) 在移动应用上,我希望目标网址为rest/member/account(返回json)

我尝试了以下但是它没有做到

public class MySwitchUserFilter extends SwitchUserFilter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        if (request.getParameter("android") != null)
            this.setTargetUrl("/rest/member/account");
        else
            this.setTargetUrl("/account");
        super.doFilter(request, response, chain);
    }
}

My Spring Security上下文

<beans:bean id="switchUserFilter"
        class="com.myapp.auth.MySwitchUserFilter">
        <beans:property name="userDetailsService" ref="userDetailsService" />
        <beans:property name="switchUserUrl" value="/admin/j_spring_security_switch_user" />
        <beans:property name="exitUserUrl" value="/j_spring_security_exit_user" />
        <beans:property name="targetUrl" value="/account" />
    </beans:bean>

当我在浏览器中执行以下网址时,我得到Access is Denied

https://localhost:8443/business/admin/j_spring_security_switch_user?j_username=test&android=1

日志

DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 1 of 12 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/login'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/authentication'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/forgot'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/resources/**'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/admin/**'
DEBUG: org.springframework.security.web.access.channel.ChannelProcessingFilter - Request: FilterInvocation: URL: /admin/j_spring_security_switch_user?j_username=test&android=1; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@fd6ed5da: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 3 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 5 of 12 in additional filter chain; firing Filter: 'BrowserAuthenticationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 8 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 9 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 10 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 11 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/login'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/authentication'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/forgot'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/resources/**'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/admin/**'
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /admin/j_spring_security_switch_user?j_username=test&android=1; Attributes: [hasAnyRole('ADMIN')]
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN
DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@1410588, returned: 1
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successful
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager did not change Authentication object
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 12 of 12 in additional filter chain; firing Filter: 'MySwitchUserFilter'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/rest/**'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 1 of 12 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/login'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/authentication'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/forgot'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/resources/**'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/admin/**'
DEBUG: org.springframework.security.web.access.channel.ChannelProcessingFilter - Request: FilterInvocation: URL: /admin/j_spring_security_switch_user?j_username=test&android=1; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@91b8a7a: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@91b8a7a: Principal: com.myapp.auth.AuthenticationUserDetails@194a73d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: MEMBER, Switch User Authority [ROLE_PREVIOUS_ADMINISTRATOR,org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN]'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 3 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 5 of 12 in additional filter chain; firing Filter: 'BrowserAuthenticationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 8 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@91b8a7a: Principal: com.myapp.auth.AuthenticationUserDetails@194a73d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: MEMBER, Switch User Authority [ROLE_PREVIOUS_ADMINISTRATOR,org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN]'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 9 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 10 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /admin/j_spring_security_switch_user?j_username=test&android=1 at position 11 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/login'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/authentication'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/forgot'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/resources/**'
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/admin/j_spring_security_switch_user'; against '/admin/**'
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /admin/j_spring_security_switch_user?j_username=test&android=1; Attributes: [hasAnyRole('ADMIN')]
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@91b8a7a: Principal: com.myapp.auth.AuthenticationUserDetails@194a73d; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: MEMBER, Switch User Authority [ROLE_PREVIOUS_ADMINISTRATOR,org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fd6ed5da: Principal: com.myapp.auth.AuthenticationUserDetails@1259255; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: EAE58863B5C733E17CDC0DFEEEE131CB; Granted Authorities: ADMIN]
DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@1410588, returned: -1
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doF

安全背景

<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.2.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- authentication manager and password hashing -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="daoAuthenticationProvider" />
    </authentication-manager>

    <beans:bean id="daoAuthenticationProvider"
        class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <beans:property name="userDetailsService" ref="userDetailsService" />
        <beans:property name="passwordEncoder" ref="passwordEncoder" />
    </beans:bean>

    <beans:bean id="authenticationSuccessHandler" class="com.myapp.auth.AuthenticationSuccessHandler"/>

    <beans:bean id="userDetailsService" name="userAuthenticationProvider"
        class="com.myapp.auth.AuthenticationUserDetailsGetter" />

    <beans:bean id="passwordEncoder"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    </beans:bean>

    <global-method-security pre-post-annotations="enabled" />

    <!-- declare the filter bean -->
    <beans:bean id="switchUserFilter"
        class="com.myapp.auth.MySwitchUserFilter">
        <beans:property name="userDetailsService" ref="userDetailsService" />
        <beans:property name="switchUserUrl" value="/admin/j_spring_security_switch_user" />
        <beans:property name="exitUserUrl" value="/j_spring_security_exit_user" />
        <beans:property name="targetUrl" value="/account" />
    </beans:bean>

    <!-- web services-->
    <http use-expressions="true" pattern="/rest/**"
            disable-url-rewriting="true" entry-point-ref="restAuthenticationEntryPoint" > 
        <intercept-url pattern="/rest/admin/**" access="hasAnyRole('ADMIN')"
                requires-channel="https" />
        <intercept-url pattern="/rest/member/**" access="hasAnyRole('ADMIN,MEMBER')"
                requires-channel="https" />
        <form-login login-processing-url="/rest/j_spring_security_check"
            authentication-success-handler-ref="restSuccessHandler"
            authentication-failure-handler-ref="restAuthenticationFailureHandler" />
        <logout delete-cookies="JSESSIONID" />
    </http>

    <!-- browser -->
    <http auto-config="false" use-expressions="true"
        entry-point-ref="loginUrlAuthenticationEntryPoint"
        disable-url-rewriting="true">
        <custom-filter ref="switchUserFilter" position="SWITCH_USER_FILTER"/>
        <custom-filter ref="jqueryCaptchaProcessingFilter"
            position="FORM_LOGIN_FILTER" />
        <intercept-url pattern="/login" access="permitAll"
            requires-channel="https" />
        <intercept-url pattern="/authentication" access="permitAll"
            requires-channel="https" />
        <intercept-url pattern="/forgot" access="permitAll"
            requires-channel="https" />
        <intercept-url pattern="/resources/**" access="permitAll"
            requires-channel="https" />
        <!-- <intercept-url pattern="/site_**" access="permitAll"
            requires-channel="https" /> -->
        <intercept-url pattern="/admin/**" access="hasAnyRole('ADMIN')"
            requires-channel="https" />
        <intercept-url pattern="/**" access="hasAnyRole('MEMBER','ADMIN')"
            requires-channel="https" />
        <session-management invalid-session-url="/login"
            session-authentication-error-url="/login">
        </session-management>
        <logout logout-url="/logout" />
    </http>

    <beans:bean id="jqueryCaptchaProcessingFilter"
        class="com.myapp.auth.BrowserAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="filterProcessesUrl" value="/authentication" />
        <beans:property name="authenticationSuccessHandler">
            <beans:bean class="com.myapp.auth.AuthenticationSuccessHandler">
                <beans:property name="alwaysUseDefaultTargetUrl"
                    value="true" />
                <beans:property name="defaultTargetUrl" value="/account" />
            </beans:bean>
        </beans:property>
        <beans:property name="authenticationFailureHandler">
            <beans:bean
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <beans:property name="defaultFailureUrl" value="/login" />
            </beans:bean>
        </beans:property>
    </beans:bean>

    <beans:bean id="loginUrlAuthenticationEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <beans:property name="loginFormUrl" value="/login" />
    </beans:bean>

</beans:beans>

1 个答案:

答案 0 :(得分:1)

我认为您可以通过这种方式获得正确的设备:

在Android客户端上设置:

DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");

This will give you the headers.

然后检查请求标头而不是参数以查看它是哪个设备。 另外,告诉访问被拒绝几乎没用,打开Spring-Security记录器调试并粘贴堆栈跟踪。

相关问题