]> source.dussan.org Git - gitblit.git/commitdiff
Start of webapp authentication.
authorJames Moger <james.moger@gitblit.com>
Wed, 13 Apr 2011 21:45:22 +0000 (17:45 -0400)
committerJames Moger <james.moger@gitblit.com>
Wed, 13 Apr 2011 21:45:22 +0000 (17:45 -0400)
12 files changed:
gitblit.properties
src/com/gitblit/Build.java
src/com/gitblit/wicket/AdminPage.java [new file with mode: 0644]
src/com/gitblit/wicket/AuthorizationStrategy.java [new file with mode: 0644]
src/com/gitblit/wicket/BasePage.html
src/com/gitblit/wicket/BasePage.java
src/com/gitblit/wicket/GitBlitWebApp.java
src/com/gitblit/wicket/GitBlitWebSession.java
src/com/gitblit/wicket/LoginPage.html [new file with mode: 0644]
src/com/gitblit/wicket/LoginPage.java [new file with mode: 0644]
src/com/gitblit/wicket/SecuredPage.java [deleted file]
src/com/gitblit/wicket/User.java [new file with mode: 0644]

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