2013-03-08 6 views
2

У меня есть приложение Spring MVC, которое использует Spring Security и регистрацию на основе форм для авторизации/аутентификации.Аутентификация Spring Security по URL

Теперь я хочу, чтобы добавить специальный URL, который включает в себя маркер, который должен быть доступен без дополнительной информации, поскольку маркер является уникальным для пользователя:

http://myserver.com/special/5f6be0c0-87d7-11e2-9e96-0800200c9a66/text.pdf

Как мне нужно настроить Spring Security для использовать этот токен для аутентификации пользователя?

+0

Вы хотите, чтобы программно выполнить аутентификацию пользователя на основе этого маркера? –

+0

Да, я хочу загрузить пользователя через этот токен из БД с помощью пользовательского UserDetailsService и полностью аутентифицировать его, как если бы он вступил в систему с логином/паролем –

+1

Полностью аутентифицировать пользователя на основе URL-адреса не очень хорошая идея. Если вы просто используете его для обеспечения доступа к этому файлу, то это, вероятно, достаточно справедливо, но я был бы осторожен, если бы он позволял им делать другие вещи, которые они обычно могут делать только с полным входом в систему. –

ответ

1

Необходимо определить ваш пользовательский фильтр предварительной проверки.

В контексте приложения безопасности в http тэгом:

<custom-filter position="PRE_AUTH_FILTER" ref="preAuthTokenFilter" /> 

Затем определите фильтр боб (и его свойства approprietly):

<beans:bean class="com.yourcompany.PreAuthTokenFilter" 
     id="preAuthTokenFilter"> 
    <beans:property name="authenticationDetailsSource" ref="authenticationDetailsSource" /> 
    <beans:property name="authenticationManager" ref="authenticationManager" /> 
    <beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/> 
</beans:bean> 

создать свой собственный фильтр простиралась от GenericFilterBean

public class PreAuthTokenFilter extends GenericFilterBean { 

private AuthenticationEntryPoint authenticationEntryPoint; 
private AuthenticationManager authenticationManager; 
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); 

@Override 
public void doFilter(ServletRequest req, ServletResponse resp, 
        FilterChain chain) throws IOException, ServletException { 
    HttpServletRequest request = (HttpServletRequest) req; 
    HttpServletResponse response = (HttpServletResponse) resp; 

    String token = getTokenFromHeader(request);//your method 

    if (StringUtils.isNotEmpty(token)) { 
     /* get user entity from DB by token, retrieve its username and password*/ 

     if (isUserTokenValid(/* some args */)) { 
      try { 
       UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); 
       authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); 
       Authentication authResult = this.authenticationManager.authenticate(authRequest); 
       SecurityContextHolder.getContext().setAuthentication(authResult); 
      } catch (AuthenticationException e) { 
      } 
     } 
    } 

    chain.doFilter(request, response); 
} 

/* 
other methods 
*/ 

Если вы не хотите или не можете получить пароль, d, чтобы создать свой собственный AbstractAuthenticationToken, который будет получать только имя пользователя, как пары (принципал) и использовать его вместо UsernamePasswordAuthenticationToken:

public class PreAuthToken extends AbstractAuthenticationToken { 

    private final Object principal; 

    public PreAuthToken(Object principal) { 
     super(null); 
     super.setAuthenticated(true); 
     this.principal = principal; 
    } 

    @Override 
    public Object getCredentials() { 
     return ""; 
    } 

    @Override 
    public Object getPrincipal() { 
     return principal; 
    } 
} 
1

Вы можете предоставить пользовательский PreAuthenticatedProcessingFilter и PreAuthenticatedAuthenticationProvider. Подробнее см. В разделе Pre-Authentication Scenarios chapiter.

0

Я столкнулся с этой проблемой и решил ее с помощью пользовательской реализации инфраструктуры службы безопасности Spring RembereMe. Вот что вам нужно сделать.

  • Определите свой собственный объект Authentication

    общественного класса LinkAuthentication расширяет AbstractAuthenticationToken { @Override getCredentials общественного объекта() { возвращение нуль; }

    @Override 
    public Object getPrincipal() 
    { 
    
        return the prncipal that that is passed in via the constructor 
    } 
    

    }

Определение

public class LinkRememberMeService implements RememberMeServices, LogoutHandler 
{  
    /** 
    * It might appear that once this method is called and returns an authentication object, that authentication should be finished and the 
    * request should proceed. However, spring security does not work that way. 
    * 
    * Once this method returns a non null authentication object, spring security still wants to run it through its authentication provider 
    * which, is totally brain dead on the part of Spring this, is why there is also a 
    * LinkAuthenticationProvider 
    * 
    */ 
    @Override 
    public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) 
    { 
     String accessUrl = ServletUtils.getApplicationUrl(request, "/special/"); 
     String requestUrl = request.getRequestURL().toString(); 
     if (requestUrl.startsWith(accessUrl)) 
     { 
      // take appart the url extract the token, find the user details object 
        // and return it. 
      LinkAuthentication linkAuthentication = new LinkAuthentication(userDetailsInstance); 
      return linkAuthentication; 
     } else 
     { 
      return null; 
     } 
    } 

    @Override 
    public void loginFail(HttpServletRequest request, HttpServletResponse response) 
    { 
    } 

    @Override 
    public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) 
    { 
    } 

    @Override 
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) 
    { 
    } 
} 


public class LinkAuthenticationProvider implements AuthenticationProvider 
{ 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException 
    { 
     // Spring Security is totally brain dead and over engineered 
     return authentication; 
    } 

    @Override 
    public boolean supports(Class<?> authentication) 
    { 
     return LinkAuthentication.class.isAssignableFrom(authentication); 
    } 

} 

Hack остальных оставшуюся часть вашей XML безопасности пружинной определить поставщик пользовательских аутентификации, и обычай запомнить службы.

P.S. если вы кодируете базовый код GUID в своем URL-адресе, это будет несколько символов короче. Вы можете использовать двоичный кодировщик/декодер base64 для кодека base64 для использования безопасных ссылок.

public static String toBase64Url(UUID uuid) 
{ 
    return Base64.encodeBase64URLSafeString(toBytes(uuid)); 
} 
Смежные вопросы