@@ -26,6 +26,9 @@ cloneUrl = https://localhost/git/ | |||
# Require authentication for http/https push/pull access of git repositories | |||
authenticatePushPull = true | |||
# Require authentication to see the web ui | |||
authenticateWebUI = true | |||
# Simple user realm file to authenticate users for push/pull | |||
realmFile = users.properties | |||
@@ -100,7 +100,7 @@ public class Build { | |||
* the byte array | |||
* @return the SHA1 checksum | |||
*/ | |||
private static String getSHA1(byte[] data) { | |||
public static String getSHA1(byte[] data) { | |||
MessageDigest md; | |||
try { | |||
md = MessageDigest.getInstance("SHA-1"); |
@@ -7,5 +7,5 @@ import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
public @interface SecuredPage { | |||
public @interface AdminPage { | |||
} |
@@ -0,0 +1,45 @@ | |||
package com.gitblit.wicket; | |||
import org.apache.wicket.Component; | |||
import org.apache.wicket.RestartResponseAtInterceptPageException; | |||
import org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener; | |||
import org.apache.wicket.authorization.strategies.page.AbstractPageAuthorizationStrategy; | |||
import com.gitblit.wicket.pages.RepositoriesPage; | |||
public class AuthorizationStrategy extends AbstractPageAuthorizationStrategy implements IUnauthorizedComponentInstantiationListener { | |||
public AuthorizationStrategy() { | |||
} | |||
@SuppressWarnings({ "unchecked", "rawtypes" }) | |||
@Override | |||
protected boolean isPageAuthorized(Class pageClass) { | |||
if (BasePage.class.isAssignableFrom(pageClass)) | |||
return isAuthorized(pageClass); | |||
// Return contruction by default | |||
return true; | |||
} | |||
@Override | |||
public void onUnauthorizedInstantiation(Component component) { | |||
if (component instanceof BasePage) { | |||
GitBlitWebSession session = GitBlitWebSession.get(); | |||
if (!session.isLoggedIn()) | |||
throw new RestartResponseAtInterceptPageException(LoginPage.class); | |||
else | |||
throw new RestartResponseAtInterceptPageException(RepositoriesPage.class); | |||
} | |||
} | |||
protected boolean isAuthorized(Class<? extends BasePage> pageClass) { | |||
GitBlitWebSession session = GitBlitWebSession.get(); | |||
if (!session.isLoggedIn()) | |||
return false; | |||
User user = session.getUser(); | |||
if (pageClass.isAnnotationPresent(AdminPage.class)) { | |||
} | |||
return true; | |||
} | |||
} |
@@ -32,7 +32,7 @@ | |||
<div style="float:right"> | |||
<a href="http://gitblit.com"><span wicket:id="gbVersion"></span></a> | |||
</div> | |||
<div wicket:id="footerText">[footer text]</div> | |||
<div wicket:id="userText">[user text]</div> | |||
</div> | |||
</body> | |||
</html> |
@@ -26,7 +26,7 @@ public abstract class BasePage extends WebPage { | |||
public BasePage(PageParameters params) { | |||
super(params); | |||
} | |||
protected void setupPage(String repositoryName, String pageName) { | |||
if (repositoryName != null && repositoryName.trim().length() > 0) { | |||
add(new Label("title", getServerName() + " - " + repositoryName)); | |||
@@ -43,7 +43,13 @@ public abstract class BasePage extends WebPage { | |||
add(new Label("pageName", pageName)); | |||
// footer | |||
add(new Label("footerText", "")); | |||
User user = null; | |||
if (StoredSettings.getBoolean("authenticateWebUI", true)) { | |||
user = GitBlitWebSession.get().getUser(); | |||
add(new Label("userText", "Logout " + user.toString())); | |||
} else { | |||
add(new Label("userText", "")); | |||
} | |||
add(new Label("gbVersion", "v" + Constants.VERSION)); | |||
if (StoredSettings.getBoolean("aggressiveHeapManagement", false)) { | |||
System.gc(); |
@@ -5,6 +5,7 @@ import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
import javax.servlet.http.Cookie; | |||
import javax.servlet.http.HttpServletRequest; | |||
import org.apache.wicket.Application; | |||
@@ -13,6 +14,7 @@ import org.apache.wicket.Request; | |||
import org.apache.wicket.Response; | |||
import org.apache.wicket.Session; | |||
import org.apache.wicket.protocol.http.WebApplication; | |||
import org.apache.wicket.protocol.http.WebResponse; | |||
import org.apache.wicket.protocol.http.request.urlcompressing.UrlCompressingWebRequestProcessor; | |||
import org.apache.wicket.protocol.http.servlet.ServletWebRequest; | |||
import org.apache.wicket.request.IRequestCycleProcessor; | |||
@@ -24,6 +26,7 @@ import org.eclipse.jgit.lib.Repository; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import com.gitblit.Constants; | |||
import com.gitblit.GitBlitServer; | |||
import com.gitblit.StoredSettings; | |||
import com.gitblit.utils.JGitUtils; | |||
@@ -31,8 +34,8 @@ import com.gitblit.wicket.models.RepositoryModel; | |||
import com.gitblit.wicket.pages.BlobDiffPage; | |||
import com.gitblit.wicket.pages.BlobPage; | |||
import com.gitblit.wicket.pages.BranchesPage; | |||
import com.gitblit.wicket.pages.CommitPage; | |||
import com.gitblit.wicket.pages.CommitDiffPage; | |||
import com.gitblit.wicket.pages.CommitPage; | |||
import com.gitblit.wicket.pages.LogPage; | |||
import com.gitblit.wicket.pages.PatchPage; | |||
import com.gitblit.wicket.pages.RawPage; | |||
@@ -44,11 +47,8 @@ import com.gitblit.wicket.pages.TicGitPage; | |||
import com.gitblit.wicket.pages.TicGitTicketPage; | |||
import com.gitblit.wicket.pages.TreePage; | |||
public class GitBlitWebApp extends WebApplication { | |||
public static int PAGING_ITEM_COUNT = 50; | |||
Logger logger = LoggerFactory.getLogger(GitBlitWebApp.class); | |||
FileResolver repositoryResolver; | |||
@@ -61,8 +61,17 @@ public class GitBlitWebApp extends WebApplication { | |||
public void init() { | |||
super.init(); | |||
// Setup page authorization mechanism | |||
if (StoredSettings.getBoolean("authenticateWebUI", false)) { | |||
AuthorizationStrategy authStrategy = new AuthorizationStrategy(); | |||
getSecuritySettings().setAuthorizationStrategy(authStrategy); | |||
getSecuritySettings().setUnauthorizedComponentInstantiationListener(authStrategy); | |||
} | |||
// Grab Browser info (like timezone, etc) | |||
getRequestCycleSettings().setGatherExtendedBrowserInfo(true); | |||
if (StoredSettings.getBoolean("useClientTimezone", false)) { | |||
getRequestCycleSettings().setGatherExtendedBrowserInfo(true); | |||
} | |||
// setup the standard gitweb-ish urls | |||
mount(new MixedParamUrlCodingStrategy("/summary", SummaryPage.class, new String[] { "r" })); | |||
@@ -77,11 +86,13 @@ public class GitBlitWebApp extends WebApplication { | |||
mount(new MixedParamUrlCodingStrategy("/blobdiff", BlobDiffPage.class, new String[] { "r", "h", "f" })); | |||
mount(new MixedParamUrlCodingStrategy("/commitdiff", CommitDiffPage.class, new String[] { "r", "h" })); | |||
mount(new MixedParamUrlCodingStrategy("/patch", PatchPage.class, new String[] { "r", "h", "f" })); | |||
// setup extended urls | |||
mount(new MixedParamUrlCodingStrategy("/ticgit", TicGitPage.class, new String[] { "r" })); | |||
mount(new MixedParamUrlCodingStrategy("/ticgittkt", TicGitTicketPage.class, new String[] { "r", "h", "f" })); | |||
mount(new MixedParamUrlCodingStrategy("/login", LoginPage.class, new String[] {})); | |||
repositories = new File(StoredSettings.getString("repositoriesFolder", "repos")); | |||
exportAll = StoredSettings.getBoolean("exportAll", true); | |||
repositoryResolver = new FileResolver(repositories, exportAll); | |||
@@ -109,6 +120,28 @@ public class GitBlitWebApp extends WebApplication { | |||
return Application.DEPLOYMENT; | |||
} | |||
public User authenticate(String username, char [] password) { | |||
return new User(username, password); | |||
} | |||
public User authenticate(Cookie[] cookies) { | |||
if (cookies != null && cookies.length > 0) { | |||
for (Cookie cookie:cookies) { | |||
if (cookie.getName().equals(Constants.NAME)) { | |||
String value = cookie.getValue(); | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
public void setCookie(WebResponse response, User user) { | |||
Cookie userCookie = new Cookie(Constants.NAME, user.getCookie()); | |||
userCookie.setMaxAge(Integer.MAX_VALUE); | |||
userCookie.setPath("/"); | |||
response.addCookie(userCookie); | |||
} | |||
public List<String> getRepositoryList() { | |||
return JGitUtils.getRepositoryList(repositories, exportAll, StoredSettings.getBoolean("nestedRepositories", true)); | |||
} |
@@ -12,6 +12,8 @@ public final class GitBlitWebSession extends WebSession { | |||
private static final long serialVersionUID = 1L; | |||
protected TimeZone timezone = null; | |||
private User user = null; | |||
public GitBlitWebSession(Request request) { | |||
super(request); | |||
@@ -19,6 +21,19 @@ public final class GitBlitWebSession extends WebSession { | |||
public void invalidate() { | |||
super.invalidate(); | |||
user = null; | |||
} | |||
public boolean isLoggedIn() { | |||
return user != null; | |||
} | |||
public User getUser() { | |||
return user; | |||
} | |||
public void setUser(User user) { | |||
this.user = user; | |||
} | |||
public TimeZone getTimezone() { |
@@ -0,0 +1,37 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" | |||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||
xml:lang="en" | |||
lang="en"> | |||
<!-- Head with Wicket-controlled resources in this package --> | |||
<wicket:head> | |||
<title wicket:id="title">[page title]</title> | |||
<wicket:link> | |||
<link rel="stylesheet" type="text/css" href="resources/gitblit.css"/> | |||
<link rel="shortcut icon" href="resources/gitblt-favicon.png" type="image/png" /> | |||
</wicket:link> | |||
</wicket:head> | |||
<body onload="document.getElementById('username').focus();"> | |||
<div> | |||
<center> | |||
<img wicket:id="logo" /><br/> | |||
<span style="font-weight:bold;" wicket:id="name">[name]</span><br/> | |||
<div> | |||
<form style="text-align:center;" wicket:id="loginForm"> | |||
<p/> | |||
Username <input type="text" id="username" wicket:id="username" value=""/> | |||
<p/> | |||
Password <input type="password" wicket:id="password" value=""/> | |||
<p/> | |||
<input type="submit" value="Login" /> | |||
<div style="background-color:#c7c7c7" wicket:id="feedback"></div> | |||
</form> | |||
</div> | |||
</center> | |||
</div> | |||
</body> | |||
</html> |
@@ -0,0 +1,101 @@ | |||
package com.gitblit.wicket; | |||
import javax.servlet.http.Cookie; | |||
import javax.servlet.http.HttpServletRequest; | |||
import org.apache.wicket.PageParameters; | |||
import org.apache.wicket.markup.html.WebPage; | |||
import org.apache.wicket.markup.html.basic.Label; | |||
import org.apache.wicket.markup.html.form.Form; | |||
import org.apache.wicket.markup.html.form.PasswordTextField; | |||
import org.apache.wicket.markup.html.form.TextField; | |||
import org.apache.wicket.markup.html.image.ContextImage; | |||
import org.apache.wicket.markup.html.panel.FeedbackPanel; | |||
import org.apache.wicket.model.IModel; | |||
import org.apache.wicket.model.Model; | |||
import org.apache.wicket.protocol.http.WebRequest; | |||
import org.apache.wicket.protocol.http.WebResponse; | |||
import org.apache.wicket.protocol.http.servlet.ServletWebRequest; | |||
import com.gitblit.Constants; | |||
public class LoginPage extends WebPage { | |||
IModel<String> username = new Model<String>(""); | |||
IModel<String> password = new Model<String>(""); | |||
public LoginPage(PageParameters params) { | |||
super(params); | |||
tryAutomaticLogin(); | |||
add(new Label("title", getServerName())); | |||
add(new ContextImage("logo", "gitblt2.png")); | |||
add(new Label("name", Constants.NAME)); | |||
Form<Void> loginForm = new LoginForm("loginForm"); | |||
loginForm.add(new TextField<String>("username", username)); | |||
loginForm.add(new PasswordTextField("password", password)); | |||
loginForm.add(new FeedbackPanel("feedback")); | |||
add(loginForm); | |||
} | |||
protected String getServerName() { | |||
ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest(); | |||
HttpServletRequest req = servletWebRequest.getHttpServletRequest(); | |||
return req.getServerName(); | |||
} | |||
class LoginForm extends Form<Void> { | |||
private static final long serialVersionUID = 1L; | |||
public LoginForm(String id) { | |||
super(id); | |||
} | |||
@Override | |||
public void onSubmit() { | |||
String username = LoginPage.this.username.getObject(); | |||
char [] password = LoginPage.this.password.getObject().toCharArray(); | |||
User user = GitBlitWebApp.get().authenticate(username, password); | |||
if (user == null) | |||
error("Invalid username or password!"); | |||
else | |||
loginUser(user); | |||
} | |||
} | |||
private void tryAutomaticLogin() { | |||
User user = null; | |||
// Grab cookie from Browser Session | |||
Cookie[] cookies = ((WebRequest) getRequestCycle().getRequest()).getCookies(); | |||
if (cookies != null && cookies.length > 0) { | |||
user = GitBlitWebApp.get().authenticate(cookies); | |||
} | |||
// Login the user | |||
loginUser(user); | |||
} | |||
private void loginUser(User user) { | |||
if (user != null) { | |||
GitBlitWebSession session = GitBlitWebSession.get(); | |||
// Set Cookie | |||
WebResponse response = (WebResponse) getRequestCycle().getResponse(); | |||
GitBlitWebApp.get().setCookie(response, user); | |||
// track user object so that we do not have to continue | |||
// re-authenticating on each request. | |||
session.setUser(user); | |||
// Redirect to original page OR to first available tab | |||
if (!continueToOriginalDestination()) { | |||
// Redirect to home page | |||
setResponsePage(session.getApplication().getHomePage()); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.gitblit.wicket; | |||
import com.gitblit.Build; | |||
import com.gitblit.Constants; | |||
public class User { | |||
private String username; | |||
private char [] password; | |||
public User(String username, char [] password) { | |||
this.username = username; | |||
this.password = password; | |||
} | |||
public String getCookie() { | |||
return Build.getSHA1((Constants.NAME + username + new String(password)).getBytes()); | |||
} | |||
public String toString() { | |||
return username; | |||
} | |||
} |