Есть две вещи, когда вы пытаетесь внедрить REST. Один из них - Аутентификация (кажется, что он у вас работает), а другой - Авторизация (именно это, как я полагаю, ваш вопрос).
То, как я обрабатывал это в dropwizard раньше, заключается в том, что при каждом входе пользователя вы возвращаете какой-то access_token (это доказывает, что они аутентифицированы) обратно клиенту, который должен быть возвращен ими в КАЖДОМ последующем вызове, который они делают как часть некоторого заголовок (обычно это делается через заголовок «Авторизация»). На стороне сервера вам нужно будет сохранить/сопоставить этот access_token с ЭТИМ пользователем, прежде чем возвращать его обратно клиенту, и когда все последовательные вызовы выполняются с этим access_token, вы ищете пользователя, сопоставленного с этим access_token, и определяете, является ли этот пользователь авторизован для доступа к этому ресурсу или нет. Теперь пример:
1) Пользователь входит в систему с помощью /myapp/signin
2) Вы аутентифицируете пользователя и отправляете обратно access_token в качестве ответа, сохраняя его на своей стороне, например, access_token -> userIdABCD
3) Клиент возвращается в /myapp/{username}/getstuff. Если клиент не предоставил заголовок «Авторизация» с предоставленным им access_token, вы должны немедленно вернуть 401 Неавторизованный код.
4) Если клиент предоставляет access_token, вы можете найти пользователя на основе того access_token, который вы сохранили на шаге № 2, и проверить, имеет ли этот userId доступ к этому ресурсу или нет. Если нет, вернуть 401 неавторизованный код, а если есть доступ, вернуть актуальные данные обратно.
Теперь перейдем к заголовку «Авторизация». Вы можете получить доступ к заголовку «Авторизация» во всех своих вызовах, используя параметр «@Context HttpServletRequest hsr», но имеет ли смысл добавлять этот параметр в каждый вызов? Нет, это не так. В этом помогают фильтры безопасности в dropwizard. Вот пример того, как добавить фильтр безопасности.
public class SecurityFilter extends OncePerRequestFilter{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException{
String accessToken = request.getHeader("Authorization");
// Do stuff here based on the access token (check for user's authorization to the resource ...
}
Итак, какой ресурс действительно защищает этот фильтр безопасности? Для этого вам нужно будет добавить этот фильтр к конкретным ресурсам, которые вы хотите защитить, что можно сделать следующим образом:
environment.addFilter(SecurityFilter, "/myapp/*");
Помните, что оба ваших URL-адреса /myapp/signin и /myapp/{username}/getstuff, оба будут проходить через этот фильтр безопасности, НО, /myapp/signin НЕ будет иметь access_token, очевидно, потому что вы не дали ни одного клиенту еще. Об этом нужно будет позаботиться в самом фильтре, например:
String url = request.getRequestURL().toString();
if(url.endsWith("signin"))
{
// Don't look for authorization header, and let the filter pass without any checks
}
else
{
// DO YOUR NORMAL AUTHORIZATION RELATED STUFF HERE
}
URL-адрес, который вы защищаете, будет зависеть от того, как структурированы ваши URL-адреса и что вы хотите защитить. Чем лучше вы спроектируете URL-адреса, тем проще будет написать фильтры безопасности для их защиты. С добавлением этого фильтра безопасности процесс будет выглядеть следующим образом:
1) Пользователь переходит в /myapp/signin. Вызов пройдет через фильтр, и из-за этого оператора «если» он продолжит ваш АКТУАЛЬНЫЙ ресурс /myapp/signin, и вы назначите access_token на основе успешной аутентификации.
2) Пользователь делает вызов /myapp/{username}/mystuff с помощью access_token. Этот вызов пройдет через тот же фильтр безопасности и пройдет через оператор «else», где вы фактически выполняете свою авторизацию. Если авторизация пройдет, вызов продолжится для вашего фактического обработчика ресурсов, и если он не авторизован, должен быть возвращен 401.
public class SecurityFilter extends OncePerRequestFilter
{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
{
String url = request.getRequestURL().toString();
String accessToken = request.getHeader("Authorization");
try
{
if (accessToken == null || accessToken.isEmpty())
{
throw new Exception(Status.UNAUTHORIZED.getStatusCode(), "Provided access token is either null or empty or does not have permissions to access this resource." + accessToken);
}
if (url.endsWith("/signin"))
{
//Don't Do anything
filterChain.doFilter(request, response);
}
else
{
//AUTHORIZE the access_token here. If authorization goes through, continue as normal, OR throw a 401 unaurhtorized exception
filterChain.doFilter(request, response);
}
}
catch (Exception ex)
{
response.setStatus(401);
response.setCharacterEncoding("UTF-8");
response.setContentType(MediaType.APPLICATION_JSON);
response.getWriter().print("Unauthorized");
}
}
}
Надеюсь, это поможет! Мне понадобилось около 2 дней, чтобы понять это самостоятельно!
person
shahshi15
schedule
18.12.2013