James Moger
2011-04-13 94b96b5a98bef254128ccc4f5fc0e0c4376324e4
Start of webapp authentication.
1 files renamed
4 files added
6 files modified
279 ■■■■■ changed files
gitblit.properties 3 ●●●●● patch | view | raw | blame | history
src/com/gitblit/Build.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/AdminPage.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/AuthorizationStrategy.java 45 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/BasePage.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/BasePage.java 8 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.java 41 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebSession.java 15 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LoginPage.html 37 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/LoginPage.java 101 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/User.java 23 ●●●●● patch | view | raw | blame | history
gitblit.properties
@@ -26,6 +26,9 @@
# 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
src/com/gitblit/Build.java
@@ -100,7 +100,7 @@
     *            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");
src/com/gitblit/wicket/AdminPage.java
File was renamed from src/com/gitblit/wicket/SecuredPage.java
@@ -7,5 +7,5 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SecuredPage {
public @interface AdminPage {
}
src/com/gitblit/wicket/AuthorizationStrategy.java
New file
@@ -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;
    }
}
src/com/gitblit/wicket/BasePage.html
@@ -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>
src/com/gitblit/wicket/BasePage.java
@@ -43,7 +43,13 @@
        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();
src/com/gitblit/wicket/GitBlitWebApp.java
@@ -5,6 +5,7 @@
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.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.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.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,10 +47,7 @@
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);
@@ -61,8 +61,17 @@
    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)
        if (StoredSettings.getBoolean("useClientTimezone", false)) {
        getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
        }
        // setup the standard gitweb-ish urls
        mount(new MixedParamUrlCodingStrategy("/summary", SummaryPage.class, new String[] { "r" }));
@@ -81,6 +90,8 @@
        // 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);
@@ -109,6 +120,28 @@
        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));
    }
src/com/gitblit/wicket/GitBlitWebSession.java
@@ -13,12 +13,27 @@
    protected TimeZone timezone = null;
    private User user = null;
    public GitBlitWebSession(Request request) {
        super(request);
    }
    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() {
src/com/gitblit/wicket/LoginPage.html
New file
@@ -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>
src/com/gitblit/wicket/LoginPage.java
New file
@@ -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());
            }
        }
    }
}
src/com/gitblit/wicket/User.java
New file
@@ -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;
    }
}