2017-04-18 132 views
-1

我正在使用Spring-MVC应用程序进行身份验证和授权。在我们的应用程序中,我们发送带有URL的电子邮件。很多时候用户没有登录,但登录后,我们希望在登录后重定向到原始链接。谢谢。尝试XML配置,但它不起作用。Spring-Security:登录后重定向到上一页(尝试其他SO链接)

XML配置:

<!-- Global Security settings --> 
    <security:http pattern="/resources/**" security="none"/> 
    <security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true"> 
     <security:form-login login-page="/login" username-parameter="j_username" password-parameter="j_password" 
          login-processing-url="/j_spring_security_check" default-target-url="/canvaslisting" 
          always-use-default-target="true" authentication-failure-url="/denied"/> 
     <security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService" 
           token-validity-seconds="1209600" data-source-ref="dataSource"/> 
     <security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/> 
     <security:intercept-url pattern="/**" requires-channel="https"/> 
     <security:port-mappings> 
      <security:port-mapping http="8080" https="8443"/> 
     </security:port-mappings> 
     <security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/> 
     <security:session-management session-fixation-protection="newSession"> 
      <security:concurrency-control session-registry-ref="sessionReg" max-sessions="5" expired-url="/login"/> 
     </security:session-management> 
     </security:http> 

    <beans:bean id="sessionReg" class="org.springframework.security.core.session.SessionRegistryImpl"/> 

    <beans:bean id="rememberMeAuthenticationProvider" 
       class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices"> 
     <beans:constructor-arg index="0" value="_spring_security_remember_me"/> 
     <beans:constructor-arg index="1" ref="userDetailsService"/> 
     <beans:constructor-arg index="2" ref="jdbcTokenRepository"/> 
     <property name="alwaysRemember" value="true"/> 
    </beans:bean> 

    <beans:bean id="jdbcTokenRepository" 
       class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl"> 
     <beans:property name="createTableOnStartup" value="false"/> 
     <beans:property name="dataSource" ref="dataSource"/> 
    </beans:bean> 

    <!-- Remember me ends here --> 
    <security:authentication-manager alias="authenticationManager"> 
     <security:authentication-provider user-service-ref="LoginServiceImpl"> 
      <security:password-encoder ref="encoder"/> 
     </security:authentication-provider> 
    </security:authentication-manager> 

    <beans:bean id="encoder" 
       class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"> 
     <beans:constructor-arg name="strength" value="11"/> 
    </beans:bean> 

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

    <beans:bean id="authenticationFilter" 
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
     <beans:property name="filterProcessesUrl" value="/login" /> 
     <beans:property name="authenticationManager" ref="authenticationManager" /> 
     <beans:property name="authenticationSuccessHandler"> 
      <beans:bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> 
       <beans:property name="useReferer" value="true"/> 
      </beans:bean> 
     </beans:property> 
     <beans:property name="authenticationFailureHandler"> 
      <beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> 
       <beans:property name="defaultFailureUrl" value="/login?login_error=t" /> 
      </beans:bean> 
     </beans:property> 
    </beans:bean> 
</beans> 

谢谢。

回答

1

虽然你没有展示你如何配置你的标签,所以我假设,你已经有了,看到下面的代码。

<security:http auto-config="true" use-expressions="false"> 
<security:form-login login-page="/login" login-processing-url="/login" 
username-parameter="custom_username" 
password-parameter="custom_password" 

default-target-url="/appointments/" 
always-use-default-target="true" 

authentication-failure-url="/login?error=true" 
     /> 

<security:intercept-url pattern="/appointments/*" access="ROLE_USER"/> 
<security:intercept-url pattern="/schedule/*" access="ROLE_FOO"/> 
<security:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER"/> 
</security:http> 

所以,如果你不提这两条线

default-target-url="/appointments/" 
always-use-default-target="true" 

,则默认情况下春季安全将您重定向用户到同一个页面(这是他的要求),并得到了验证提示。

如果仍然没有填满您的需求,那么您可能需要实现自己的过滤器或查看FilterSecurityInterceptor或MethodSecurityInterceptor。

+0

谢谢您的回答,我已经贴了拦截,但SO上编辑过程中得到了注释。你能否检查更新后的帖子,我将always-use-default设置为True,但是我希望当某个链接从Email中被点击并且用户没有通过验证时,用户在登录后返回到前一个URL,而不是默认目标网址。谢谢。 –

+0

@WeareBorg如果您将使用always-use-default = true,那么无论如何,您的用户将被重定向到您的default-target-url,因此您有两个选项可以删除您的default-target-url并设置您的自定义http标题为邮件url或任何你想要的网址,然后在你的控制器或拦截器中重定向,第二种选择是,如果你不想写一些自定义过滤器,就用你目前的方法吧 – KAmit

+0

我已经写了一个authenticationFilter,但它不起作用。它位于XML配置的底部。这不够吗?或者我还需要对/ login进行更改... –

1

贝娄是一个例子,这将帮助你实现你的目标:

为了更好地理解这个问题,看看在下面的例子: - 用户收到他被邀请参加的投票更美丽的一个通讯邮件假期图片。该URL包含用于在页面中验证用户的哈希参数。 - 当用户点击给定的URL时,它将作为已经过认证的用户到达投票页面。

所以我的自定义过滤器将像波纹管:

public class OneShotActionFilter extends GenericFilterBean { 

private static final Logger LOGGER = 
LoggerFactory.getLogger(OneShotActionFilter.class); 
private static Map<String, String> users = new HashMap<String, String>(); 
static { 
users.put("0000000000001", "bartosz"); 
users.put("0000000000002", "admin"); 
users.put("0000000000003", "mod"); 
} 
private static final String PARAM_NAME = "uio"; 
private AuthenticationManager authenticationManager; 
private UserDetailsService userDetailsService; 
private final RedirectStrategy redirectStrategy = new 
DefaultRedirectStrategy(); 

private enum AuthenticationStates { 
REDIRECT, CONTINUE; 
} 

public void setAuthenticationManager(AuthenticationManager 
authenticationManager) { 
this.authenticationManager = authenticationManager; 
} 

public void setUserDetailsService(UserDetailsService userDetailsService) { 
this.userDetailsService = userDetailsService; 
} 

@Override 
public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain filterChain) throws IOException, 
ServletException { 
LOGGER.debug("One shot filter invoked"); 
if (attemptAuthentication(request) == AuthenticationStates.REDIRECT) { 
    // Note that we should handle that dynamically but for learning purposes 
    //we'll consider that one-shot 
    // authentication works only for this URL 
    this.redirectStrategy.sendRedirect((HttpServletRequest) request, 
(HttpServletResponse) response, 
    "/secret/one-shot-action"); 
} else { 
    LOGGER.debug("User was not correctly authenticated, continue filter chain"); 
    // continue execution of all other filters 
    // You can test the code without this fragment in the pages without ?uio parameter. You should see blank page because of 
    // security filter chain interruption. 
    filterChain.doFilter(request, response); 
} 
} 

private AuthenticationStates attemptAuthentication(ServletRequest request) { 
AuthenticationStates state = AuthenticationStates.CONTINUE; 
Authentication authentication = 
SecurityContextHolder.getContext().getAuthentication(); 
String code = request.getParameter(PARAM_NAME); 
if ((authentication == null || !authentication.isAuthenticated()) && code != 
null && 
    users.containsKey(code)) { 
    LOGGER.debug("Checking user for code "+code); 
    UserDetails user = userDetailsService.loadUserByUsername(users.get(code)); 
    LOGGER.debug("Found user from code ("+users.get(code)+"). User found is "+user); 
    if (user != null) { 
     users.remove(code); 
     UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user.getUsername(), 
     user.getPassword()); 
    authentication = this.authenticationManager.authenticate(authRequest); 
    if (authentication != null && authentication.isAuthenticated()) { 
     SecurityContextHolder.getContext().setAuthentication(authentication); 
     state = AuthenticationStates.REDIRECT; 
    } 
    } 
} 
return state; 
} 
} 

终于在你的XML配置它,像波纹管

<security:http authentication-manager-ref="frontend" auto-config="true" use- 
expressions="true" access-denied-page="/access-denied"> 
<-- other filters are defined here --> 
<security:custom-filter ref="oneShootAuthFilter" 
after="CONCURRENT_SESSION_FILTER"/> 
</security:http> 

<bean id="oneShootAuthFilter" 
class="com.waitingforcode.security.filter.OneShotActionFilter"> 
<property name="authenticationManager" ref="frontend" /> 
<property name="userDetailsService" ref="inMemoryUserService" /> 
</bean> 

为了测试过滤器,我们可以尝试访问http://localhost:8080/?uio=0000000000001。你应该重定向(但只有一次)到http://localhost:8080/secret/one-shot-action页面

我写了这个例子为更清晰和作为未来的问题参考。 如果您认为这有助于您清除疑问,请进行投票。

你也可以访问this链接

相关问题