У меня проблема с попыткой интегрировать аутентификацию токена с Spring Security в существующий проект Spring + Hibernate.
Я создал Entity для пользователя (User), DAO (UserDAO) и Сервиса(UserService).Затем я создал фильтр и применил его в web.xml:
<filter>
<filter-name>springSecurityTokenFilter</filter-name>
<filter-class>com.ivt.da.security.TokenAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityTokenFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Вот код фильтра:
public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public TokenAuthenticationFilter() {
super("/**");
this.setAuthenticationManager(new TokenAuthenticationManager()); // <-------- here's a problem
setAuthenticationSuccessHandler((request, response, authentication) ->
{
SecurityContextHolder.getContext().setAuthentication(authentication);
request.getRequestDispatcher(request.getServletPath() + request.getPathInfo()).forward(request, response);
});
setAuthenticationFailureHandler((request, response, authenticationException) -> {
response.getOutputStream().print(authenticationException.getMessage());
});
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String token = request.getHeader("token");
if (token == null)
token = request.getParameter("token");
if (token == null) {
TokenAuthentication authentication = new TokenAuthentication(null);
authentication.setAuthenticated(false);
return authentication;
}
TokenAuthentication tokenAuthentication = new TokenAuthentication(token);
Authentication authentication = getAuthenticationManager().authenticate(tokenAuthentication);
return authentication;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
super.doFilter(req, res, chain);
}
Проблема заключается в том, что мне нужно установить собственный диспетчер проверки подлинности.Но созданный мной Диспетчер использует службу, которая должна быть подключена автоматически:
@Service
public class TokenAuthenticationManager implements AuthenticationManager {
@Autowired
private UserService usersService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
if (authentication instanceof TokenAuthentication) {
TokenAuthentication readyTokenAuthentication = processAuthentication((TokenAuthentication) authentication);
return readyTokenAuthentication;
} else {
authentication.setAuthenticated(false);
return authentication;
}
} catch (Exception ex) {
if(ex instanceof AuthenticationServiceException)
throw ex;
}
return null;
}
private TokenAuthentication processAuthentication(TokenAuthentication authentication) throws AuthenticationException {
String token = authentication.getToken();
String key = Base64.getEncoder().encodeToString("here gonna be a secret key".getBytes());
DefaultClaims claims;
// ...
// tokenParsingThings
// ...
Date expiredDate = new Date(claims.get("token_expiration_date", Long.class));
if (expiredDate.after(new Date()))
return buildFullTokenAuthentication(authentication, claims);
else
throw new AuthenticationServiceException("Token expired date error");
}
@Transactional
public TokenAuthentication buildFullTokenAuthentication(TokenAuthentication authentication, DefaultClaims claims) {
User user = usersService.loadUserByUsername(claims.get("USERNAME", String.class)); // <--- NPE, cuz service has not been autowired
if (user.isEnabled()) {
Role role = user.getRole();
List<String> roles = new ArrayList<>();
roles.add(role.getRole());
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(role.getRole()));
TokenAuthentication fullTokenAuthentication =
new TokenAuthentication(authentication.getToken(), authorities, true, user);
return fullTokenAuthentication;
} else {
throw new AuthenticationServiceException("User disabled");
}
}
Я знаю, что она не подключает Службу автоматически, потому что я создаю объект Manager с использованием оператора new вФильтр конструктор.Однако я не могу внедрить (или могу?) Настройку Auth Manager, используя также @Autowire, поскольку класс Filter не является компонентом, который допускает использование этой аннотации.
Класс обслуживания должен быть подключен автоматически, поскольку онDAO внедрен, и DAO имеет сессию и так далее, поэтому я не могу просто создать UserServiceImpl вручную, используя new
Кроме того, важно использовать конфигурацию XML, потому что весь проектиспользует XML-конфиги.
Есть ли способ сделать TokenAuthenticationManager доступным со всем, что внутри автоматически подключено?Может быть, я могу передать параметр TokenAuthenticationManager в фильтр в качестве аргумента конструктора или что-то в этом роде.Пожалуйста, помогите с этим.
Заранее спасибо