Skip to content

Commit

Permalink
First cut of adding a login page and related session handling
Browse files Browse the repository at this point in the history
  • Loading branch information
gashcrumb committed Jul 25, 2013
1 parent 4b06936 commit 1cc8b2b
Show file tree
Hide file tree
Showing 17 changed files with 330 additions and 84 deletions.
@@ -0,0 +1,8 @@
package io.hawt.system;

/**
* @author Stan Lewis
*/
public enum AuthenticateResult {
AUTHORIZED, NOT_AUTHORIZED, NO_CREDENTIALS
}
17 changes: 12 additions & 5 deletions hawtio-web/src/main/java/io/hawt/system/Authenticator.java
Expand Up @@ -49,12 +49,12 @@ public static void extractAuthInfo(String authHeader, ExtractAuthInfoCallback cb

}

public static boolean authenticate(String realm, String role, HttpServletRequest request) {
public static AuthenticateResult authenticate(String realm, String role, HttpServletRequest request) {

String authHeader = request.getHeader(HEADER_AUTHORIZATION);

if (authHeader == null || authHeader.equals("")) {
return false;
return AuthenticateResult.NO_CREDENTIALS;
}

final AuthInfo info = new AuthInfo();
Expand All @@ -67,23 +67,30 @@ public void getAuthInfo(String userName, String password) {
}
});

if (info.username.equals("public")) {
return AuthenticateResult.NO_CREDENTIALS;
}

if (info.set()) {

Subject subject = doAuthenticate(realm, role, info.username, info.password);
if (subject == null) {
return false;
return AuthenticateResult.NOT_AUTHORIZED;
}

SubjectThreadLocal.put(subject);

/*
HttpSession session = request.getSession(true);
session.setAttribute("user", user);
session.setAttribute("org.osgi.service.http.authentication.remote.user", user);
session.setAttribute("org.osgi.service.http.authentication.type", HttpServletRequest.BASIC_AUTH);
*/
return true;
return AuthenticateResult.AUTHORIZED;
}


return false;
return AuthenticateResult.NO_CREDENTIALS;
}

private static Subject doAuthenticate(String realm, String role, final String username, final String password) {
Expand Down
41 changes: 41 additions & 0 deletions hawtio-web/src/main/java/io/hawt/system/Helpers.java
@@ -0,0 +1,41 @@
package io.hawt.system;

import io.hawt.web.AuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* @author Stan Lewis
*/
public class Helpers {

private static final transient Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";

public static void doForbidden(HttpServletResponse response) {
try {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentLength(0);
response.flushBuffer();
} catch (IOException ioe) {
LOG.debug("Failed to send forbidden response: {}", ioe);
}
}

public static void doAuthPrompt(String realm, HttpServletResponse response) {
// request authentication
try {
response.setHeader(HEADER_WWW_AUTHENTICATE, Authenticator.AUTHENTICATION_SCHEME_BASIC + " realm=\"" + realm + "\"");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.flushBuffer();
} catch (IOException ioe) {
LOG.debug("Failed to send auth response: {}", ioe);
}

}
}
21 changes: 21 additions & 0 deletions hawtio-web/src/main/java/io/hawt/system/SubjectThreadLocal.java
@@ -0,0 +1,21 @@
package io.hawt.system;

import javax.security.auth.Subject;

/**
* @author Stan Lewis
*/
public class SubjectThreadLocal {

private static final ThreadLocal<Subject> tsSubject = new ThreadLocal<Subject>();

public static void put(Subject subject) {
tsSubject.set(subject);
}

public static Subject take() {
Subject answer = tsSubject.get();
tsSubject.remove();
return answer;
}
}
37 changes: 15 additions & 22 deletions hawtio-web/src/main/java/io/hawt/web/AuthenticationFilter.java
@@ -1,6 +1,7 @@
package io.hawt.web;

import io.hawt.system.Authenticator;
import io.hawt.system.Helpers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -17,8 +18,6 @@ public class AuthenticationFilter implements Filter {

private static final transient Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";

private String realm;
private String role;
private boolean enabled;
Expand Down Expand Up @@ -59,36 +58,30 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha

String path = httpRequest.getServletPath();

boolean doAuthenticate = !(path.startsWith("/jolokia") && path.startsWith("/proxy") && path.startsWith("/upload") && path.startsWith("/javadoc"));
boolean doAuthenticate = path.startsWith("/auth") ||
path.startsWith("/jolokia") ||
path.startsWith("/upload");

if (doAuthenticate) {
LOG.debug("Doing authentication and authorization for path {}", path);
if (Authenticator.authenticate(realm, role, httpRequest)) {
chain.doFilter(request, response);
} else {
doAuthPrompt((HttpServletResponse)response);
switch (Authenticator.authenticate(realm, role, httpRequest)) {
case AUTHORIZED:
chain.doFilter(request, response);
break;
case NOT_AUTHORIZED:
Helpers.doForbidden((HttpServletResponse) response);
break;
case NO_CREDENTIALS:
//doAuthPrompt((HttpServletResponse)response);
Helpers.doForbidden((HttpServletResponse) response);
break;
}
} else {
chain.doFilter(request, response);
}
}


public void doAuthPrompt(HttpServletResponse response) {
// request authentication
try {
response.setHeader(HEADER_WWW_AUTHENTICATE, Authenticator.AUTHENTICATION_SCHEME_BASIC + " realm=\"" + this.realm + "\"");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.flushBuffer();
} catch (IOException ioe) {
LOG.debug("Failed to send auth response: {}", ioe);
}

}



@Override
public void destroy() {
LOG.info("Destroying hawtio authentication filter");
Expand Down
40 changes: 0 additions & 40 deletions hawtio-web/src/main/java/io/hawt/web/AuthenticationServlet.java

This file was deleted.

53 changes: 53 additions & 0 deletions hawtio-web/src/main/java/io/hawt/web/LoginServlet.java
@@ -0,0 +1,53 @@
package io.hawt.web;

import io.hawt.system.Helpers;
import io.hawt.system.SubjectThreadLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.security.auth.Subject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import java.util.GregorianCalendar;
import java.util.Set;

/**
* @author Stan Lewis
*/
public class LoginServlet extends HttpServlet {

private static final transient Logger LOG = LoggerFactory.getLogger(LoginServlet.class);

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

Subject subject = SubjectThreadLocal.take();
if (subject == null) {
Helpers.doForbidden(resp);
return;
}
Set<Principal> principals = subject.getPrincipals();

String username = null;

for (Principal principal : principals) {
if (principal.getClass().getSimpleName().equals("UserPrincipal")) {
LOG.info("Authorizing user " + username);
username = principal.getName();
}
}

HttpSession session = req.getSession(true);
session.setAttribute("user", username);
session.setAttribute("org.osgi.service.http.authentication.remote.user", username);
session.setAttribute("org.osgi.service.http.authentication.type", HttpServletRequest.BASIC_AUTH);
session.setAttribute("loginTime", GregorianCalendar.getInstance().getTimeInMillis());
session.setMaxInactiveInterval(900);
}

}
13 changes: 8 additions & 5 deletions hawtio-web/src/main/webapp/WEB-INF/web.xml
Expand Up @@ -32,6 +32,10 @@
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/jolokia/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/auth/*</url-pattern>
</filter-mapping>
<!--
don't want to try and interpret the authentication header
intended for the proxy
Expand All @@ -49,7 +53,6 @@
<url-pattern>/javadoc/*</url-pattern>
</filter-mapping>


<servlet>
<servlet-name>jolokia-agent</servlet-name>
<servlet-class>org.jolokia.http.AgentServlet</servlet-class>
Expand Down Expand Up @@ -86,12 +89,12 @@
</servlet-mapping>

<servlet>
<servlet-name>authentication</servlet-name>
<servlet-class>io.hawt.web.AuthenticationServlet</servlet-class>
<servlet-name>login</servlet-name>
<servlet-class>io.hawt.web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>authentication</servlet-name>
<url-pattern>/auth/*</url-pattern>
<servlet-name>login</servlet-name>
<url-pattern>/auth/login/*</url-pattern>
</servlet-mapping>


Expand Down
19 changes: 19 additions & 0 deletions hawtio-web/src/main/webapp/app/core/html/login.html
@@ -0,0 +1,19 @@
<div ng-controller="Core.LoginController">


<div class="login-wrapper">
<div class="login-form">
<form name="login" class="form-inline" ng-submit="doLogin()">
<input type="text" class="input-medium" placeholder="User Name" required ng-model="username">
<input type="password" class="input-medium" placeholder="Password" required ng-model="password">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn btn-success" ng-disabled="!login.$valid"><i class="icon-check"></i> Sign In</button>
</form>
</div>
</div>


</div>

25 changes: 24 additions & 1 deletion hawtio-web/src/main/webapp/app/core/js/app.ts
@@ -1,10 +1,16 @@
module Core {

export function AppController($scope, $location, workspace, $document, pageTitle, localStorage) {
export function AppController($scope, $location, workspace, $document, pageTitle, localStorage, userDetails, lastLocation) {

if (userDetails.username === null) {
// sigh, hack
$location.url('/help');
}

$scope.collapse = '';
$scope.match = null;
$scope.pageTitle = pageTitle.exclude('hawtio');
$scope.userDetails = userDetails;

$scope.setPageTitle = () => {
var tab = workspace.getActiveTab();
Expand Down Expand Up @@ -35,8 +41,25 @@ module Core {
}
}

$scope.loggedIn = () => {
return userDetails.username !== null && userDetails.username !== 'public';
}

$scope.$watch(() => { return localStorage['regexs'] }, $scope.setRegexIndicator);

$scope.$watch('userDetails', (newValue, oldValue) => {
if (userDetails.username === null) {
lastLocation.url = $location.url('/login');
}
console.log("userDetails: ", userDetails);
}, true);

$scope.$on('$routeChangeStart', function() {
if (userDetails.username === null) {
lastLocation.url = $location.url('/login');
}
});

$scope.$on('$routeChangeSuccess', function() {
$scope.setPageTitle();
$scope.setRegexIndicator();
Expand Down

0 comments on commit 1cc8b2b

Please sign in to comment.