Я запускаю весеннее веб-приложение в tomcat9, которое находится за apache2. Только пользователи, прошедшие аутентификацию в apache, могут получить доступ к приложению, и request.getRemoteUser () уже возвращает имя пользователя, как его видит apache. Я также могу получить свои сущности пользователя, вызвав userRepository.findByAuth0id (request.getRemoteUser ());
Прочитав некоторые из превосходных ответов здесь, я пришел к следующему:
Аутентификацияфильтр:
public class RemoteAuthenticationFilter implements Filter {
@Autowired
private UserRepository userRepository;
@Override
public void init(final FilterConfig fc) throws ServletException {
}
@Override
public void doFilter(
final ServletRequest req, final ServletResponse res, final FilterChain fc
) throws IOException, ServletException {
final SecurityContext context = SecurityContextHolder.getContext();
if (
context.getAuthentication() != null &&
context.getAuthentication().isAuthenticated()
) {
// do nothing
} else {
final HttpServletRequest httpRequest = (HttpServletRequest) req;
final String auth0id = httpRequest.getRemoteUser();
final List<User> users =
userRepository.findByAuth0id(auth0id);
if (users.size() == 0)
return;
final Authentication auth = new RemoteAuthentication(users.get(0));
SecurityContextHolder.getContext().setAuthentication(auth);
}
fc.doFilter(req, res);
}
@Override
public void destroy() {
}
}
Класс аутентификации:
public class RemoteAuthentication implements Authentication {
private static final long serialVersionUID = 1L;
private final User user;
public RemoteAuthentication(final User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return new ArrayList<>(0);
}
@Override
public Object getCredentials() {
return user.getAuth0id();
}
@Override
public Object getDetails() {
return user;
}
@Override
public Object getPrincipal() {
return user.getLogin();
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(final boolean isAuthenticated)
throws IllegalArgumentException {
}
@Override
public String getName() {
return user.getLogin();
}
}
bean в src / main / webapp / WEB-INF / applicationContext.xml:
<bean id="authTokenFilter" class="com.kodekonveyor.market.authentication.RemoteAuthenticationFilter" scope="singleton" />
src / main / webapp / WEB-INF / spring / security.xml:
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
<http >
<custom-filter ref="authTokenFilter" after="BASIC_AUTH_FILTER" />
</http>
</b:beans>
Код в одном из сервлетов, который уже может аутентифицироваться вручную с помощью request.getRemoteUser ():
final Authentication authentication =
SecurityContextHolder
.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
if (null == authentication)
loggerService.call("authentication is null");
else {
final String currentUserName = authentication.getName();
loggerService.call("current username from spring:" + currentUserName);
}
} else
loggerService.call("spring sees anon user");
Я вижу "аутентификация нулевая" в журналах.
Что я пропустил? Я также заинтересован в других, более эффективных способах достижения того же самого. Если бы я мог получить имя удаленного пользователя без запроса http, мне этого было бы достаточно.