OK, Roller now does scheme enforcement via Acegi configured via roller.properties. Since I'm new to Acegi, I've summarized the changes below for your review.

- Dave


========== roller.properties

If you want to protect URLs by using HTTPS, you simply turn on scheme enforcement in your roller.properties override file. You can use Ant- style URL patterns to specify which URLs need HTTPS. For example, this turns on HTTPS for the user profile and admin pages:

    # Enable scheme enforcement?
# Scheme enforcement ensures that specific URLs are viewed only via HTTPS
    schemeenforcement.enabled=true
    # URL patterns that require HTTPS
schemeenforcement.https.urls=/editor/yourProfile.do*,/admin/ user.do*

Like secure login, scheme enforcement defaults to false.

Note that I don't list the login pages as those are already configured via the securelogin.enabled property.


========== RollerContext.java : initializeSecurityFeatures()

Inside Roller's context init, here's what we do to tell Acegi about our protected URLs:

if (RollerConfig.getBooleanProperty ("schemeenforcement.enabled")) {

            ChannelProcessingFilter procfilter =
(ChannelProcessingFilter)ctx.getBean ("channelProcessingFilter"); ConfigAttributeDefinition secureDef = new ConfigAttributeDefinition(); secureDef.addConfigAttribute(new SecurityConfig ("REQUIRES_SECURE_CHANNEL")); ConfigAttributeDefinition insecureDef = new ConfigAttributeDefinition(); insecureDef.addConfigAttribute(new SecurityConfig ("REQUIRES_INSECURE_CHANNEL"));
            PathBasedFilterInvocationDefinitionMap defmap =
(PathBasedFilterInvocationDefinitionMap) procfilter.getFilterInvocationDefinitionSource();

            // add HTTPS URL path patterns to Acegi config
String httpsUrlsProp = RollerConfig.getProperty ("schemeenforcement.https.urls");
            if (httpsUrlsProp != null) {
String[] httpsUrls = StringUtils.stripAll (StringUtils.split(httpsUrlsProp, ",") );
                for (int i=0; i<httpsUrls.length; i++) {
                    defmap.addSecureUrl(httpsUrls[i], secureDef);
                }
            }
            // all other action URLs are non-HTTPS
            defmap.addSecureUrl("/**/*.do*", insecureDef);
        }

It wasn't exactly easy to figure out how to do that, BTW.


========== Cleanup

We don't use these anymore so I deleted them:

    SslUtil.java
    SecureTag.java
    SchemeEnforcementFilter.java
    securelogin.http.port property
    securelogin.https.port property
    securelogin.https.headername property
    securelogin.https.headervalue property








On Jan 9, 2006, at 12:26 PM, Matt Raible wrote:

On 1/9/06, Allen Gilliland <[EMAIL PROTECTED]> wrote:
Matt is the authority on Acegi, but I believe there is a way to list the urls that Acegi should guarantee for SSL transport in the security.xml.
Then Acegi takes care of the protocol switching.  Right now I don't
think some of our secure login property info is being mapped to the
Acegi config, so we still need to do that.

I believe I did handle this as part of the integration, but didn't
test it.  If it doesn't work, let me know and I'll fix it.


I definitely think that we shouldn't need the old "secure" tag that we
were using and I'm also not sure that we need to continue with old
secureheader stuff. I've moved the secureheader stuff outside of Roller
for blogs.sun.com and I think that's the proper place for it.

Right, Acegi Security should be able to handle anything that the
"secure" tag did.  Also, I didn't account for the secureheader stuff,
so moving it outside Roller would be great. ;-)


-- Allen


On Mon, 2006-01-09 at 07:47, Dave Johnson wrote:
Regarding:
http://opensource2.atlassian.com/projects/roller/browse/ROL-989

The user profile page allows a user to change his/her password and
sends passwords in the clear, so I'd to make it more secure for sites that require HTTPS for logins. The easiest way to do this seems to be
to force HTTPS on that page and that's what I've done in my local
workspace.

Here's a summary of my changes (code is below): inside the
YourProfileAction.edit() method, I check to see if secure login is
enabled. If secure login is enabled but the current request is not
secure, I redirect to a secure version of the URL.

I have two questions before I continue this work and add the same code
to user-admin:
1) Is this the right way to do this, given that we're now using Acegi?

You shouldn't need any code, just configure it in security.xml.
Unfortunately, I don't think there's a way to say "only require SSL if
secure login is enabled". ;-)

... so maybe you will need some code.

Matt

2) Do we need the <roller:secure> tag on any of our pages anymore, now
that we're using Acegi?

- Dave



PS: here are the specific changes:


==================== roller.properties

Roller properties needs to change to allow the YourProfileAction to
run under HTTPS.

schemeenforcement.https.urls=/j_security_check,/auth,/login- redirect.jsp,/login.jsp,/editor/yourProfile.do



==================== YourProfileAction.java

The YourProfileAction.java method needs code to test for
securelogin.enabled and isSecure(). We can't use the <roller:secure>
tag on the JSP page because by the time we get there the response is
already committed.


         ActionForward forward =
mapping.findForward("yourProfile.page");
         try
         {
+            if
(RollerConfig.getBooleanProperty("securelogin.enabled") &&
!SslUtil.isSecure(request)) {
+                response.sendRedirect(SslUtil.getRedirectString(
+                    request,
request.getSession().getServletContext(), true));
+                return mapping.findForward("access-denied");
+            }
             RollerSession rollerSession =
RollerSession.getRollerSession(request);
             UserData ud = rollerSession.getAuthenticatedUser();
             UserFormEx form = (UserFormEx)actionForm;



==================== SslUtil.java

We need a way to test isSecure() using the appropirate properties:

+    /**
+     * Test for HTTPS connection by using request.isSecure() or,
+     * if httpsHeaderName is set, test for reqest header instead.
+ * If httpsHeaderValue is also set, test for that specific value.
+     */
+    public static boolean isSecure(HttpServletRequest request) {
+        String httpsHeaderName =
RollerConfig.getProperty("securelogin.https.headername");
+        String httpsHeaderValue =
RollerConfig.getProperty("securelogin.https.headervalue");
+        boolean secure = false;
+        if (httpsHeaderName == null) {
+            secure = request.isSecure();
+        } else {
+ String headerValue = request.getHeader (httpsHeaderName); + if (headerValue != null && headerValue.trim().length () >
0) {
+                secure = httpsHeaderValue==null ||
httpsHeaderValue.equals(headerValue);
+            }
+        }
+        return secure;
+    }
+




Reply via email to