Password authentication
This commit is contained in:
parent
5e8529e89e
commit
c4ea40899a
1
.idea/artifacts/MoviesWebApp_war_exploded.xml
generated
1
.idea/artifacts/MoviesWebApp_war_exploded.xml
generated
@ -17,6 +17,7 @@
|
||||
<element id="archive" name="MoviesCommon-1.0.0-SNAPSHOT.jar">
|
||||
<element id="module-output" name="MoviesCommon" />
|
||||
</element>
|
||||
<element id="library" level="project" name="Maven: commons-codec:commons-codec:1.13" />
|
||||
</element>
|
||||
</element>
|
||||
<element id="directory" name="META-INF">
|
||||
|
11
.idea/dataSources.xml
generated
Normal file
11
.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="db_movies@localhost" uuid="7782f0d2-6685-4308-9359-efdc01dfeba0">
|
||||
<driver-ref>mysql.8</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mysql://localhost:3306/db_movies</jdbc-url>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
@ -85,6 +85,38 @@
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**.*</include>
|
||||
</includes>
|
||||
<targetPath>classes</targetPath>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/jaxws</directory>
|
||||
<includes>
|
||||
<include>authfile</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>initialize</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.helger.maven</groupId>
|
||||
<artifactId>jaxws-maven-plugin</artifactId>
|
||||
@ -95,6 +127,7 @@
|
||||
</wsdlUrls>
|
||||
<packageName>at.technikumwien.movies.generated</packageName>
|
||||
<sourceDestDir>${project.build.directory}/generated</sourceDestDir>
|
||||
<xauthFile>${project.build.directory}/authfile</xauthFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@ -114,4 +147,9 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<movies.user>moviesuser</movies.user>
|
||||
<movies.password>topsecret</movies.password>
|
||||
</properties>
|
||||
</project>
|
||||
|
1
MoviesClient/src/jaxws/authfile
Normal file
1
MoviesClient/src/jaxws/authfile
Normal file
@ -0,0 +1 @@
|
||||
http://${movies.user}:${movies.password}@localhost:8080/movieservice/MoviesWebService?wsdl
|
@ -7,7 +7,9 @@ import java.util.List;
|
||||
|
||||
public class MovieResourceClient {
|
||||
public static void main(String[] args) {
|
||||
var target = ClientBuilder.newClient().target("http://localhost:8080/movieservice/resources/movie");
|
||||
var target = ClientBuilder.newClient()
|
||||
.register(new RequestFilter("moviesuser", "topsecret"))
|
||||
.target("http://localhost:8080/movieservice/resources/movie");
|
||||
|
||||
List<Movie> allMovies = target
|
||||
.request(MediaType.APPLICATION_XML)
|
||||
|
@ -10,6 +10,8 @@ import java.util.List;
|
||||
|
||||
public class MoviesWebServiceClient {
|
||||
public static void main(String[] args) throws Exception {
|
||||
PasswordAuthenticator.install("moviesuser", "topsecret");
|
||||
|
||||
MoviesWebService_Service service = new MoviesWebService_Service();
|
||||
MoviesWebService port = service.getMoviesWebServicePort();
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetAddress;
|
||||
import java.net.PasswordAuthentication;
|
||||
import java.net.URL;
|
||||
|
||||
public class PasswordAuthenticator {
|
||||
private PasswordAuthenticator() {}
|
||||
|
||||
public static void install(String username, String password) {
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password.toCharArray());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import javax.ws.rs.client.ClientRequestContext;
|
||||
import javax.ws.rs.client.ClientRequestFilter;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class RequestFilter implements ClientRequestFilter {
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public RequestFilter(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(ClientRequestContext request) throws IOException {
|
||||
var token = username + ":" + password;
|
||||
var basicAuthentication = "Basic " + DatatypeConverter.printBase64Binary(token.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
request.getHeaders().add("Authorization", basicAuthentication);
|
||||
}
|
||||
}
|
@ -13,7 +13,8 @@
|
||||
let options = {
|
||||
mode: "cors",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
"Accept": "application/json",
|
||||
"Authorization": "Basic " + btoa("moviesuser:topsecret")
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
<facet type="web" name="Web">
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<deploymentDescriptor name="jboss-web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/jboss-web.xml" />
|
||||
<deploymentDescriptor name="web.xml" url="file://$MODULE_DIR$/src/main/webapp/WEB-INF/web.xml" />
|
||||
</descriptors>
|
||||
<webroots>
|
||||
@ -75,5 +76,6 @@
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: jakarta.xml.soap:jakarta.xml.soap-api:1.4.1" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: jakarta.jws:jakarta.jws-api:1.1.1" level="project" />
|
||||
<orderEntry type="module" module-name="MoviesCommon" />
|
||||
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.13" level="project" />
|
||||
</component>
|
||||
</module>
|
@ -45,6 +45,12 @@
|
||||
<artifactId>MoviesCommon</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.13</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -1,5 +1,6 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.core.Context;
|
||||
@ -10,6 +11,7 @@ import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@Path("/movie")
|
||||
@RolesAllowed("MoviesUserRole")
|
||||
public class MovieResource {
|
||||
@Inject
|
||||
private MoviesService moviesService;
|
||||
|
@ -0,0 +1,24 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import javax.annotation.security.DeclareRoles;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition;
|
||||
import javax.security.enterprise.identitystore.DatabaseIdentityStoreDefinition;
|
||||
|
||||
@BasicAuthenticationMechanismDefinition(realmName = "MoviesWebApp")
|
||||
@DeclareRoles({
|
||||
"MoviesAdminRole",
|
||||
"MoviesUerRole"
|
||||
})
|
||||
@DatabaseIdentityStoreDefinition(
|
||||
dataSourceLookup = "java:jboss/datasources/MoviesDS",
|
||||
callerQuery = "SELECT password FROM t_user WHERE username = ?",
|
||||
groupsQuery = "SELECT r.rolename FROM t_user u " +
|
||||
"INNER JOIN t_user_role ur ON u.id = ur.userid " +
|
||||
"INNER JOIN t_role r ON ur.roleid = r.id " +
|
||||
"WHERE u.username = ?",
|
||||
hashAlgorithm = SH2HexPasswordHash.class
|
||||
)
|
||||
@ApplicationScoped
|
||||
public class MovieSecurityConfig {
|
||||
}
|
@ -1,16 +1,20 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ejb.*;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.security.enterprise.SecurityContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Stateless
|
||||
@TransactionManagement(value=TransactionManagementType.CONTAINER)
|
||||
@RolesAllowed("MoviesUserRole")
|
||||
public class MoviesService {
|
||||
private static final Logger LOGGER = Logger.getLogger(MoviesService.class.getName());
|
||||
|
||||
@ -20,6 +24,9 @@ public class MoviesService {
|
||||
@PersistenceContext(unitName = "MoviesPU")
|
||||
private EntityManager em;
|
||||
|
||||
@Inject
|
||||
private SecurityContext securityContext;
|
||||
|
||||
public Movie findById(long id) {
|
||||
LOGGER.info("findById() >> id=" + id);
|
||||
|
||||
@ -42,6 +49,9 @@ public class MoviesService {
|
||||
public List<Movie> findAll() {
|
||||
LOGGER.info("findAll()");
|
||||
|
||||
LOGGER.info("> principal: " + (securityContext.getCallerPrincipal() != null ? securityContext.getCallerPrincipal().getName() : null));
|
||||
LOGGER.info("> role('MoviesUserRole'): " + (securityContext.isCallerInRole("MoviesUserRole")));
|
||||
|
||||
return em.createNamedQuery("Movies.selectAll", Movie.class) //JPQL -> java persistence query language
|
||||
.getResultList();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package at.technikumwien.movies;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.HttpConstraint;
|
||||
import javax.servlet.annotation.ServletSecurity;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -10,6 +12,9 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@WebServlet(urlPatterns = "movieserviceservlet")
|
||||
@ServletSecurity(
|
||||
@HttpConstraint(rolesAllowed = "MoviesUserRole")
|
||||
)
|
||||
public class MoviesServlet extends HttpServlet {
|
||||
@Inject
|
||||
private MoviesService moviesService;
|
||||
|
@ -0,0 +1,18 @@
|
||||
package at.technikumwien.movies;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import javax.security.enterprise.identitystore.PasswordHash;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SH2HexPasswordHash implements PasswordHash {
|
||||
@Override
|
||||
public String generate(char[] chars) {
|
||||
return DigestUtils.sha512Hex(new String(chars));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(char[] chars, String s) {
|
||||
return Objects.equals(generate(chars), s);
|
||||
}
|
||||
}
|
@ -7,9 +7,12 @@
|
||||
<jta-data-source>java:jboss/datasources/MoviesDS</jta-data-source>
|
||||
<jar-file>lib/MoviesCommon-1.0.0-SNAPSHOT.jar</jar-file>
|
||||
<properties>
|
||||
<property name="javax.persistence.sql-load-script-source" value="META-INF/sql/security-data.sql"/>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
|
||||
<property name="hibernate.show_sql" value="true"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="update" />
|
||||
<property name="hibernate.hbm2ddl.import_files_sql_extractor"
|
||||
value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="update"/> <!-- value="create-drop" for loading security-data.sql -->
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
|
@ -0,0 +1,31 @@
|
||||
DROP TABLE IF EXISTS t_user_role;
|
||||
DROP TABLE IF EXISTS t_user;
|
||||
DROP TABLE IF EXISTS t_role;
|
||||
|
||||
CREATE TABLE t_user (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(25) NOT NULL,
|
||||
password VARCHAR(128) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t_role (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
rolename VARCHAR(25) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE t_user_role (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
userid INT NOT NULL,
|
||||
roleid INT NOT NULL,
|
||||
FOREIGN KEY (userid) REFERENCES t_user(id),
|
||||
FOREIGN KEY (roleid) REFERENCES t_role(id)
|
||||
);
|
||||
|
||||
INSERT INTO t_user (id, username, password) VALUES (1, 'moviesadmin', SHA2('topsecret', 512));
|
||||
INSERT INTO t_user (id, username, password) VALUES (2, 'moviesuser', SHA2('topsecret', 512));
|
||||
|
||||
INSERT INTO t_role (id, rolename) VALUES (1, 'MoviesAdminRole');
|
||||
INSERT INTO t_role (id, rolename) VALUES (2, 'MoviesUserRole');
|
||||
|
||||
INSERT INTO t_user_role (id, userid, roleid) VALUES (1, 1, 1);
|
||||
INSERT INTO t_user_role (id, userid, roleid) VALUES (2, 2, 2);
|
7
MoviesWebApp/src/main/webapp/WEB-INF/jboss-web.xml
Normal file
7
MoviesWebApp/src/main/webapp/WEB-INF/jboss-web.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema"
|
||||
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_14_0.xsd"
|
||||
version="14.0">
|
||||
<security-domain>jaspitest</security-domain>
|
||||
</jboss-web>
|
@ -17,4 +17,30 @@
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<url-pattern>*.xhtml</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<context-param>
|
||||
<param-name>resteasy.role.based.security</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>MoviesWebApp</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<http-method-omission>OPTIONS</http-method-omission>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
<user-data-constraint>
|
||||
<transport-guarantee>NONE</transport-guarantee> <!-- CONFIDENTIAL -> only HTTPS possible -->
|
||||
</user-data-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<security-role>
|
||||
<role-name>MoviesAdminRole</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>MoviesUserRole</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
||||
|
Loading…
x
Reference in New Issue
Block a user