Улучшение алгоритма авторизации в RESTFull приложение JAX-RS(Jersey)
Всем привет :)
У меня есть рабочая реализация Basic Authorization с ролями, под JAX-RS(Jersey), но она кажется мне не сильно оптимальной.
Если у вас есть более удачные примеры реализации или объективная критика, жду.
web.xml
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.barbecue.security.CustomApplication</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
AuthenticationFilter.java
@Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter
{
@Context
private ResourceInfo resourceInfo;
private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final String AUTHENTICATION_SCHEME = "Basic";
@Override
public void filter(ContainerRequestContext requestContext)
{
Method method = resourceInfo.getResourceMethod();
//Access allowed for all
if( ! method.isAnnotationPresent(PermitAll.class))
{
//Access denied for all
if(method.isAnnotationPresent(DenyAll.class))
{
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
.entity("Access blocked for all users !!").build());
return;
}
//Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
//Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
//If no authorization information present; block access
if(authorization == null || authorization.isEmpty())
{
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
.entity("You cannot access this resource").build());
return;
}
//Get encoded username and password
final String encodedUserPassword = authorization.get(0).replaceFirst(AUTHENTICATION_SCHEME + " ", "");
//Decode username and password
String usernameAndPassword = new String(Base64.decodeBase64(encodedUserPassword.getBytes()));
//Split username and password tokens
final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
final String username = tokenizer.nextToken();
final String password = tokenizer.nextToken();
//Verify user access
if(method.isAnnotationPresent(RolesAllowed.class))
{
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
//Is user valid?
if( ! isUserAllowed(username, password, rolesSet))
{
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
.entity("You cannot access this resource").build());
return;
}
}
}
}
private boolean isUserAllowed(final String username, final String password, final Set<String> rolesSet)
{
boolean isAllowed = false;
try {
Class.forName("org.postgresql.Driver");
Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432", "postgres", "postgres");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("" +
"select account.pass " +
"from file_manager.account account " +
"where account.user_name = '" + username + "';");
while(resultSet.next()) {
if (resultSet.getString("pass").equals(password)) {
isAllowed = true;
} else {
isAllowed = false;
}
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return isAllowed;
}
}
CustomApplication.java
public class CustomApplication extends ResourceConfig
{
private static final String packages = "org.barbecue.module";
public CustomApplication()
{
packages(packages);
register(FileRest.class);
register(AccountRest.class);
register(AuthenticationFilter.class);
}
}