如何自定义Spring安全切换用户?
How to customize Spring Security switch user?
我在我的网络应用程序中启用了切换用户。现在我想在移动应用程序上做一些类似的事情,但是目标 URL 应该不同。
在网络应用程序上,目标 URL 是 /account
(returns jsp)
在移动应用程序上,我希望目标 URL 为 rest/member/account
(returns 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);
}
}
我的 Spring 安全上下文
<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>
当我在浏览器中执行以下 URL 时,我得到 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>
我认为您可以通过这种方式获得合适的设备:
在 Android 客户端上设置:
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");
This will give you the headers.
并检查请求 header 而不是参数以查看它是哪个设备。
另外,告知访问被拒绝几乎没有用,打开 Spring-Security 记录器进行调试并将堆栈跟踪粘贴到您的 post.
我在我的网络应用程序中启用了切换用户。现在我想在移动应用程序上做一些类似的事情,但是目标 URL 应该不同。
在网络应用程序上,目标 URL 是 /account
(returns jsp)
在移动应用程序上,我希望目标 URL 为 rest/member/account
(returns 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);
}
}
我的 Spring 安全上下文
<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>
当我在浏览器中执行以下 URL 时,我得到 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>
我认为您可以通过这种方式获得合适的设备:
在 Android 客户端上设置:
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android");
This will give you the headers.
并检查请求 header 而不是参数以查看它是哪个设备。 另外,告知访问被拒绝几乎没有用,打开 Spring-Security 记录器进行调试并将堆栈跟踪粘贴到您的 post.