2015-12-02 2 views
0

Это часть моей конфигурацииSpring 4 Аякса Войти перенаправлять запрошенному URL

public class CustomWebSecurityConfigurer extends WebSecurityConfigurerAdapter { 
    private static final String LOGIN_URL = "/#login"; 
    @Override 
    protected void configure(final HttpSecurity http) throws Exception { 
     final String adminAccess = String.format("hasAnyRole('ROLE_%s', 'ROLE_%s')", 
       Role.SYSTEM_ADMINISTRATOR, Role.USER_ADMINISTRATOR); 
     http.authorizeRequests().antMatchers("/admin/**").access(adminAccess).and().formLogin() 
       .loginPage(LOGIN_URL); 
    } 
} 

Как можно видеть, только Войти запускает стартовую страницу и #login используется, чтобы показать диалог модальный входа в систему, который посылает войдите в систему с помощью AJAX.

Следующий код - это логин.

@RequestMapping(value = "/login", method = RequestMethod.POST) 
ResponseEntity<Map<String, Object>> login(@RequestBody final JSONCredentials credentials) { 
    log.debug("Test: {}", requestCache == null ? "null" : requestCache.getClass()); 
    final Authentication auth = new UsernamePasswordAuthenticationToken(credentials.getUsername(), 
      credentials.getPassword()); 
    final Authentication authenticated = authenticationManager.authenticate(auth); 
    if (authenticated.isAuthenticated()) { 
     SecurityContextHolder.getContext().setAuthentication(authenticated); 
     return get(); 
    } 
    SecurityContextHolder.clearContext(); 
    throw new BadCredentialsException(""); 
} 

он выполняет метод аутентификации и звонков.

@RequestMapping(method = RequestMethod.GET) 
ResponseEntity<Map<String, Object>> get() { 
    final Map<String, Object> result = new HashMap<>(); 
    final Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    if (auth != null) { 
     result.put("principal", auth.getPrincipal()); 
    } 
    result.put("redirectTo", "URL where I come from"); 
    return ResponseEntity.ok(result); 
} 

Поэтому, когда я открываю/admin, я перенаправлен в/# login. Откроется диалоговое окно входа в систему, и вход в систему будет успешным, но мне нравится перенаправлять исходный URL.
Исходный URL должен быть известен весной, возвращен как ответ входа в систему AJAX, а JavaScript просто должен изменить местоположение.

ответ

0

В то же время я реализовал решение, которое очень хорошо работает для нас.

Сначала я создал AccessFilter, который проверяет, происходит ли перенаправление на настроенный URL-адрес входа.

public class AccessFilter extends OncePerRequestFilter { 
    private static final Logger log = LoggerFactory.getLogger(AccessFilter.class); 

    @Inject private SessionContext ctx; 
    @Inject private Environment env; 

    @Override 
    protected void doFilterInternal(final HttpServletRequest request, 
      final HttpServletResponse response, final FilterChain filterChain) 
      throws ServletException, IOException { 
     filterChain.doFilter(request, response); 
     if (response.getStatus() == 302 && response.getHeaderNames().contains("Location") 
       && response.getHeader("Location").contains("#login")) { 
      final String vrkroot = env.getProperty("VRK_HOST_NAME"); 
      final String myRoot = vrkroot.replaceAll("^https?://.+?/", "/"); 
      final String redirect = myRoot + request.getServletPath().replaceFirst("/", "") 
        + (request.getQueryString() != null ? "?" + request.getQueryString() : ""); 
      log.debug("URL: {}, Query: {}, Redirect: {}", request.getRequestURL().toString(), 
        request.getQueryString(), redirect); 
      ctx.setAfterLoginRedirect(redirect); 
     } 
    } 
} 

Переменная среды VRK_HOST_NAME используется для определения реального URL система использует. Это необходимо, потому что Tomcat 8 Server находится за веб-сервером Apache, который перенаправляется на Tomcat Context.

http://www.mydomain.de/ > localhost:8080/<ContextRoot> 

Я не нашел другого простого способа определить фактический URL.

myRoot содержит относительный корень моего приложения с точки зрения Apache, а не точку Tomcat. Это актуально только в том случае, если мое приложение не находится в корне. MyAppName может быть другим, чем ContextRoot.

http://www.mydomain.de/MyAppName 

Наконец, URL-адрес перенаправления вычисляется и хранится в объекте/переменной контекста.

@Component 
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) 
public class SessionContext implements Serializable { 
    private static final long serialVersionUID = -8618385704526830047L; 
    private String afterLoginRedirect; 

    public String getAfterLoginRedirect() { 
     return afterLoginRedirect; 
    } 

    public void setAfterLoginRedirect(final String afterLoginRedirect) { 
     this.afterLoginRedirect = afterLoginRedirect; 
    } 
} 

Последний элемент - это контроллер, который обрабатывает логин AJAX.

@RequestMapping(value = "/login", method = RequestMethod.POST) 
ResponseEntity<Map<String, Object>> login(@RequestBody final JSONCredentials credentials) { 
    final Authentication auth = new UsernamePasswordAuthenticationToken(credentials.getUsername(), 
      credentials.getPassword()); 
    final Authentication authenticated = authenticationManager.authenticate(auth); 
    if (authenticated.isAuthenticated()) { 
     SecurityContextHolder.getContext().setAuthentication(authenticated); 
     return get(); 
    } 
    SecurityContextHolder.clearContext(); 
    throw new BadCredentialsException(""); 
} 

@RequestMapping(method = RequestMethod.GET) 
ResponseEntity<Map<String, Object>> get() { 
    final Map<String, Object> result = new HashMap<>(); 
    final Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder 
      .getRequestAttributes()).getRequest(); 
    final CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); 
    final HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder 
      .getRequestAttributes()).getResponse(); 
    response.addHeader("X-CSRF-TOKEN", csrfToken.getToken()); 
    if (auth != null) { 
     result.put("principal", auth.getPrincipal()); 
     if (!Strings.isNullOrEmpty(ctx.getAfterLoginRedirect())) { 
      result.put("redirectTo", ctx.getAfterLoginRedirect()); 
      ctx.setAfterLoginRedirect(null); 
     } 
    } 
    return ResponseEntity.ok(result); 
} 

Эти оба метода в контроллере будут делать логин и возвращать информацию, которая я на данный момент. В методе get URL-адрес перенаправления отправляется клиенту, и, наконец, JavaScript выполняет перенаправление.

Надеюсь, это полезно.

Смежные вопросы