我当前的 Spring MVC 应用程序最初设计为仅适用于经过身份验证的用户,因此使用应用程序用户将导航到www.myappdomain.com
. 但是现在我想将这些资源迁移到下www.myappdomain.com/member
,并将以前的资源用作静态网站(或任何人都可以访问)。
我能想到的一种解决方案是修改所有控制器,RequestMapping("member")
但这也需要我修改 JSP 中的所有映射。
有没有其他更方便的方式来实现我想要的?
更新
根据 M. Deinum 给出的答案,我决定创建额外的 servlet 名称。但是,每次我尝试登录(使用或不使用正确的凭据)时,我都会被重定向到登录页面。
web.xml
<servlet>
<servlet-name>site</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>site</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/member/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/member/*</url-pattern>
</filter-mapping>
安全上下文.xml
<http pattern="/**/favicon.ico" security="none" />
<http pattern="/**/resources/**" security="none" />
<http pattern="/maintenance.html" security="none" />
<http auto-config="false" use-expressions="true"
disable-url-rewriting="true">
<intercept-url pattern="/member/login*" access="permitAll"
requires-channel="https" />
<form-login authentication-success-handler-ref="myAuthenticationSuccessHandler"
login-page="/member/login" authentication-failure-url="/member/loginFailed" />
<intercept-url pattern="/member/**" access="isFullyAuthenticated()"
requires-channel="https" />
<session-management
session-authentication-error-url="/member/loginFailed">
<concurrency-control error-if-maximum-exceeded="true"
max-sessions="1" />
</session-management>
<logout invalidate-session="true" delete-cookies="JSESSIONID" />
</http>
登录.jsp
<form method="POST" action="<c:url value='j_spring_security_check'/>"
autocomplete="off">
<fieldset>
<label for="username"><spring:message code="label.username" />
<span class="ico"><img src="${imgPath}/user.png"
alt="Username Icon" border="0"></span></label> <input type="text"
name="j_username" id="username" required autofocus> <label
for="password"><spring:message code="label.password" /> <span
class="ico"><img src="${imgPath}/pass.png"
alt="Password Icon" border="0"></span></label> <input type="password"
name="j_password" id="password" required>
</fieldset>
<c:if test="${!empty errorMsg}">
<div class="errorMessage">
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}</div>
</c:if>
<fieldset>
<button type="submit">
>>
<spring:message code="label.go" />
</button>
</fieldset>
</form>
一旦我按下登录表单中的提交按钮,就会生成调试跟踪。
org.springframework.web
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'app' processing GET request for [/dnag2/member/login]
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /login
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public java.lang.String com.dnag2.controller.AuthenticationController.initLogin(org.springframework.ui.ModelMap,javax.servlet.http.HttpServletRequest)]
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/dnag2/member/login] is: -1
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'login'; URL [/WEB-INF/views/login.jsp]] in DispatcherServlet with name 'app'
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/login.jsp] in InternalResourceView 'login'
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request
org.springframework.security
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/**/favicon.ico'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/**/resources/**'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/maintenance.html'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 1 of 11 in additional filter chain; firing Filter: 'ChannelProcessingFilter'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/member/login*'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/member/**'
DEBUG: org.springframework.security.web.access.channel.ChannelProcessingFilter - Request: FilterInvocation: URL: /member/j_spring_security_check; ConfigAttributes: [REQUIRES_SECURE_CHANNEL]
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@2d4d3ce6. A new one will be created.
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 3 of 11 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: FACD6A03C058DB14AFEE4FF7BAF6A1FA; Granted Authorities: ROLE_ANONYMOUS'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /member/j_spring_security_check at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/member/login*'
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/member/j_spring_security_check'; against '/member/**'
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /member/j_spring_security_check; Attributes: [isFullyAuthenticated()]
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: FACD6A03C058DB14AFEE4FF7BAF6A1FA; Granted Authorities: ROLE_ANONYMOUS
DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@72ffa2f5, returned: -1
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
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:54)
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.doFilter(AbstractAuthenticationProcessingFilter.java:183)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)