Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ user1=passwd1


## If you want simple, basic authentication user/password
## on the operations,
## on the operations, where all authenticated users are authorized
## 1 - set a better password in [users] above.
## 2 - comment out the "/$/** = localhost" line and use:
##/$/** = authcBasic,user[admin]
##/$/** = authcBasic,user

##

## or to allow any access.
##/$/** = anon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@

package org.apache.jena.fuseki.mod.shiro;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.net.Authenticator;
import java.net.http.HttpClient;

import java.util.regex.Pattern;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import org.apache.jena.atlas.lib.Lib;
Expand All @@ -52,6 +50,8 @@
import org.apache.jena.sparql.exec.http.GSP;
import org.apache.jena.sparql.exec.http.QueryExecHTTP;

import static org.junit.jupiter.api.Assertions.*;

public class TestModShiro {
static final String unlocal = determineUnlocal();
static final String localRE = "(localhost)|(127.0.0.1)|(::1)";
Expand Down Expand Up @@ -168,13 +168,29 @@ private FusekiServer.Builder serverBuilderWithShiro(String filename) {
AuthEnv.get().unregisterUsernamePassword(server.serverURL());
}

// try the ping (proxy for admin operations)
// try the ping (proxy for admin operations as admin user)
Pattern startOfDateTimePattern = Pattern.compile("[0-9]{4}-.*");
{
Authenticator authenticator = AuthLib.authenticator("admin", "pw");
HttpClient httpClient = HttpEnv.httpClientBuilder().authenticator(authenticator).build();
HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
String pingResultString = HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
assertTrue(startOfDateTimePattern.matcher(pingResultString).find(),
"admin user should be able to ping: " + pingResultString);
AuthEnv.get().unregisterUsernamePassword(server.serverURL());
}
// try the ping (proxy for operations as user1 user without access)
{
// check that PingResult is still unauthorized
HttpClient httpClientAnon = HttpEnv.httpClientBuilder().build();
HttpException httpEx = assertThrows(HttpException.class, ()->HttpOp.httpGetString(httpClientAnon, server.serverURL()+"$/ping"));
assertEquals(401, httpEx.getStatusCode(), "Expect HTTP 401 if not logged in");
Authenticator authenticator = AuthLib.authenticator("user1", "passwd1");
HttpClient httpClient = HttpEnv.httpClientBuilder().authenticator(authenticator).build();
String pingResultString = HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
assertFalse(startOfDateTimePattern.matcher(pingResultString).find(),
"user1 user should not be able to ping: " + pingResultString);
}


{
// Bad password
Expand All @@ -189,6 +205,87 @@ private FusekiServer.Builder serverBuilderWithShiro(String filename) {
}
}

@Test public void access_userPassword_group() {
String dsname = "/ds";
DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
FusekiServer server = serverBuilderWithShiro("testing/Shiro/shiro_user_group_password.ini")
.add(dsname, dsg)
.enablePing(true)
.build();
server.start();

String URL = server.datasetURL(dsname);

try {
// No user-password
{
HttpException httpEx = assertThrows(HttpException.class, ()->attemptByLocalhost(server, dsname));
assertEquals(401, httpEx.getStatusCode(), "Expected HTTP 401");
}

// user-password via authenticator: localhost
{
Authenticator authenticator = AuthLib.authenticator("user1", "passwd1");
HttpClient httpClient = HttpEnv.httpClientBuilder().authenticator(authenticator).build();
attemptByLocalhost(server, httpClient, dsname);
// and a SPARQL query
QueryExecHTTP.service(URL).httpClient(httpClient).query("ASK{}").ask();
}

// user-password via registration
{
AuthEnv.get().registerUsernamePassword(server.serverURL(), "user1", "passwd1");
attemptByLocalhost(server, dsname);
AuthEnv.get().unregisterUsernamePassword(server.serverURL());
}

// try the ping (proxy for admin operations as admin user)
Pattern startOfDateTimePattern = Pattern.compile("[0-9]{4}-.*");
{
Authenticator authenticator = AuthLib.authenticator("admin", "pw");
HttpClient httpClient = HttpEnv.httpClientBuilder().authenticator(authenticator).build();
String pingResultString = HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
assertTrue(startOfDateTimePattern.matcher(pingResultString).find(),
"admin user should be able to ping: " + pingResultString);
AuthEnv.get().unregisterUsernamePassword(server.serverURL());
}
// try the ping (proxy for operations as user1 user without access)
{
// check that PingResult is still unauthorized
HttpClient httpClientAnon = HttpEnv.httpClientBuilder().build();
HttpException httpEx = assertThrows(HttpException.class, ()->HttpOp.httpGetString(httpClientAnon, server.serverURL()+"$/ping"));
assertEquals(401, httpEx.getStatusCode(), "Expect HTTP 401 if not logged in");
Authenticator authenticator = AuthLib.authenticator("user1", "passwd1");
HttpClient httpClient = HttpEnv.httpClientBuilder().authenticator(authenticator).build();
// check again that the user is logged in and can access ds
HttpOp.httpGetString(httpClient, server.datasetURL(dsname));
System.out.println(server.serverURL()+ "$/ping");
//String pingResultString = HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
//assertEquals(pingResultString, "OK", "PingResult: " + pingResultString);

// String pingResultString = HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping");
// assertEquals(pingResultString, "OK", "PingResult: " + pingResultString);
HttpException httpEx2 = assertThrows(HttpException.class, ()->HttpOp.httpGetString(httpClient, server.serverURL()+"$/ping"));
assertEquals(403, httpEx2.getStatusCode(), "Expect HTTP 403 if not logged in" + httpEx2.getResponse() + httpEx2.getMessage() + httpEx2.getStatusLine() + httpEx2.getStatusCode());

// assertFalse(startOfDateTimePattern.matcher(pingResultString).find(),
// "user1 user should not be able to ping: " + pingResultString);
}
{
// Bad password
AuthEnv.get().registerUsernamePassword(server.serverURL(), "user1", "passwd2");
// attemptByLocalhost(server, dsname);
HttpException httpEx = assertThrows(HttpException.class, ()->attemptByLocalhost(server, dsname));
assertEquals(401, httpEx.getStatusCode(), "Expected HTTP 401");
AuthEnv.get().unregisterUsernamePassword(server.serverURL());
}

} finally {
server.stop();
}
}


@Test public void shiroByCommandLine() {
String dsname = "/ds";
FusekiModule fmod = FMod_Shiro.create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ logger.http.level = INFO
logger.riot.name = org.apache.jena.riot
logger.riot.level = INFO

logger.riot.name = org.apache.shiro
logger.riot.level = WARN
logger.shiro.name = org.apache.shiro
logger.shiro.level = DEBUG

logger.jetty.name = org.eclipse.jetty
logger.jetty.level = WARN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0

[main]
plainMatcher=org.apache.shiro.authc.credential.SimpleCredentialsMatcher
[users]
admin=pw,admin
user1=passwd1,user

[urls]
/$/ping = authcBasic,roles[admin]
/ds = authcBasic,roles[user]
/$/stats = anon
/** = anon