Nicely done Dave.
I had thought the Acegi stuff for setting the secure urls would have been
easier, but oh well. That's always one of the drawbacks to using new
frameworks, there is often a steep learning curve :/
-- Allen
On Tue, 2006-01-10 at 07:36, David M Johnson wrote:
> 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;
> >>> + }
> >>> +
> >>>
> >>
> >>
>