Две сферы в одном приложении с Spring Безопасность?
Мы создаем веб-приложение, доступное как для аутентифицированных, так и для анонимных пользователей. Если вы решите не регистрироваться/войти, у вас есть только ограниченный набор функций. Аутентификация пользователя выполняется по OpenID с помощью Spring Security. Это прекрасно работает.
Однако приложение также поставляется с пользовательским интерфейсом администратора, который развертывается в <host>/<context-root>/admin
. Можем ли мы иметь две отдельные сферы с помощью Spring Безопасность (например, базовый auth для /admin/**
)? Как это нужно настроить?
Ответы
Ответ 1
Spring Безопасность добавила поддержку для этого сценария в версии 3.1, которая в настоящее время доступна как кандидат на выпуск. Это было реализовано SEC-1171, а подробности синтаксиса приведены в руководстве, включенном в 3.1.
Однако он довольно прост в использовании. В основном вы просто определяете несколько элементов http
в конфигурации Spring Security, по одному для каждой области. Мы используем его следующим образом:
<!-- Configure realm for system administration users -->
<security:http pattern="/admin/**" create-session="stateless">
<security:intercept-url pattern='/**' access='ROLE_ADMIN' requires-channel="https" />
<security:http-basic/>
</security:http>
<!-- Configure realm for standard users -->
<security:http auto-config="true" access-denied-page="/error/noaccess" use-expressions="true" create-session="ifRequired">
<security:form-login login-page="/login"
...
...
</security:http>
Ключевым моментом является pattern="/admin/**"
для первого элемента http
. Это сообщает Spring, что все URL-адреса под /admin
подчиняются этой области, а не области по умолчанию, и поэтому URL-адреса под /admin
используют вместо этого базовую проверку подлинности.
Ответ 2
Возможное решение:
- Добавить перехватчик URL для
/admin
требуется "ROLE_ADMIN"
- Настроить экземпляр
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
для перехвата URL /admin
и аутентификации пользователя как ROLE_ADMIN, если он предоставляет соответствующие учетные данные
Пример конфигурации:
<security:intercept-url pattern="/admin" access="ROLE_ADMIN"/>
<bean id="basicAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName"
value="WS realm"/>
</bean>
<bean id="basicAuthenticationProcessingFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager"
ref="authenticationManager"/>
<property name="authenticationEntryPoint"
ref="basicAuthenticationEntryPoint"/>
</bean>
Примечание: реализация по умолчанию BasicAuthenticationFilter - это пассивный фильтр, т.е. он просто ищет базовый заголовок auth в запросе, а если нет - ничего не делает. Если вы хотите, чтобы фильтр явно запрашивал базовую аутентификацию от клиента, вам необходимо расширить реализацию по умолчанию, чтобы перейти к точке входа в аутентификацию:
public class BasicAuthenticationFilter
extends org.springframework.security.web.authentication.www.BasicAuthenticationFilter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
String header = request.getHeader("Authorization");
if ((header != null) && header.startsWith("Basic ")) {
super.doFilter(req, res, chain);
} else {
getAuthenticationEntryPoint().commence(request, response, new AuthenticationCredentialsNotFoundException("Missing credentials"));
}
}
}
Кроме того, вам нужно настроить фильтр для применения только к URL /admin
- либо путем жесткого кодирования в методе doFilter
, либо путем предоставления соответствующей оболочки bean.
Ответ 3
Я не могу думать о прямом способе иметь две сферы (и сам я не пробовал):
вы можете определить два фильтра в вашем web.xml, где каждая из них имеет другую конфигурацию spring и ergo собственную среду. Глобальные вещи входят в конфигурацию приложения, специфичную для области в конфигурации фильтра.
если он используется только для другого метода auth, вы можете написать свой собственный фильтр, который затем решает, какой фильтр вызывать.