Announcement Announcement Module
No announcement yet.
Architecture questions Struts/Service/Dao + Acegi Page Title Module
Move Remove Collapse
This topic is closed
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Architecture questions Struts/Service/Dao + Acegi

    I have a web app with architecture following AppFuse and the Oreilly article

    My layers are:
    View: JSP
    Controller: Struts
    Service: Interfaces / Implementation
    DAO: Interfaces / Hibernate Implementation
    Model: POJO (With Xdoclet declarations for hibernate)

    Service and DAO layers are wired with spring, and the services are injected into the controller layer.

    The Contacts sample app has 3 parts to the service layer to my 2. The ContactManagerFacade adds security specific logic to getById, but does nothing for save or delete, which seems odd. The Backend class compares to my ServiceImpl which has a dao injected into it. Is this considered the best approach, to insert a security manager infront of the XYZManagerImpl class?

    I am making an intranet app, and the app server is behind apache with a siteminder plugin. Thus, any requests coming in are already authenticated, and only the username is passed in. All I would check is that the username exists and has not been deactivated. Would I use the TestingAuthenticationToken in this case, despite the claim that users will not deploy this Token to a production system?

    I also find it confusing that the doc states in 1.2 (Introduction) that acegi "does not have a notion of roles or groups", yet the Contacts app has ROLE_TELLER, ROLE_SUPERVISOR throughout.

    My other point of confusion is that spring creates beans as singletons by default, but the ContactManagerBackend doesn't look threadsafe. I realize it's a "quick and dirty" sample app, but it can be difficult to ascertain which parts of the code are by design and which might be oversights.

    I'm still evaluating whether or not Acegi is too immature as the version # suggests, and/or if it will be too complex for an app with simple needs. It looks like a great system with headroom, so hopefully it will fit my needs here. On a different topic, I'm looking forward to Hibernate 3's automatic permission based filtering of result sets. I haven't even looked into the code, but hopefully this will integrate well with Acegi.

    Thanks for the help,

  • #2
    I just answered the group vs role comments a few minutes ago at

    I'm not sure how Apache passes in the authenticated username. You wouldn't use the testing provider. You'd need to write a implementation which can "read" wherever the username comes from, test it is correct by delegation to an AuthenticationManager, and if so, record it in the HttpSession. After this one-off event, subsequent requests will be processed by Acegi Security as the HttpSessionIntegrationFilter will "read" the HttpSession and "write" it to the ContextHolder for the duration of the request, making the ContextHolder null at the end of the request. During the request any secure object invocations will read the Authentication from the ContextHolder, pass it to the AuthenticationManager for re-validation, and then grant or deny access accordingly. I'd recommend you take a look at how the two classes in net.sf.acegisecurity.ui.basicauth work. You'd probably do something almost identical to read the Apache processed authentication.

    The Contact sample app is quick and dirty and on reflection I would have done it differently. One of the objectives of the sample was to show how run-as authentication replacement works, but I don't think it's a feature many people would want to use so it just complicates the sample. In normal applications you'd use FilterSecurityInterceptor to secure your web request URLs, and MethodSecurityInterceptor to secure your business methods - if you felt the need. Using MethodSecurityInterceptor may complicate simple applications. If you have simple needs that are effectively handled by URL security, just use URL security. If you have a medium or large application where objects may be called from many different web views, or you need access control list or more advanced security logic (eg like the Contacts application denies access to contacts not owned by the user) you need MethodSecurityInterceptor.
    Last edited by robyn; May 14th, 2006, 04:50 PM.


    • #3
      Regarding the version number, I wouldn't let that put you off. It is not a significant reflection of maturity.

      Like any open source system, you should look at the changelog (to establish API stability and bug levels), release frequency (to establish if there is active development) and the community support (to ensure people can help you). The upgrade-xx-xx.txt files also show what non-backward compatible changes we've made. As you can see, there haven't been too many and each was fairly painless to perform.


      • #4
        Getting the username is very simple. I have the following line in a Struts LoginAction:

        String username = request.getHeader("sm_user");

        In my older apps, I would pass this username (and password in apps where i had one) to the service layer, which goes to the dao, then to the db, loads the user object and I would store it in the Session scope. Obviously this had all of my security at the controller layer, and it will be much better to have this in the service layer instead.

        The only problem with the version # is when using various open source tools in an app for a client. In this app, I was asked to use Struts 1.1, and I chose Spring and Hibernate. When management asked about Hibernate, I said it was version 2.1.4. Spring was 1.0, which made management uncomfortable. If they find out this is 0.6, I'll have to do a lot of convincing. Management is used to commercial apps, where if MS word jumps from version 2 to version 6, it MUST be a huge improvement.

        I was also confused by RunAsManager and RunAsServer, as you touched on earlier. I will use MethodSecurityInterceptor, but have no need for URL security in this app. I'll learn that part later on.


        • #5
          Just kind of musing about this (because we have Siteminder too, but I'm not yet using it with Acegi)...

          If you wanted to use the AuthenticationProcessingFilter and AutoIntegrationFilter to help manage the SecureContext into the ContextHolder, all you'd really need to do is remap the "sm_user" HttpRequest header (note that some people use different header keys) into a j_username parameter and post it into /j_acegi_security_check when the user logs in. You could alternatively extend AuthenticationProcessingFilter to pick this value up directly, then wire it to your authenticationDao to grab entitlements. Viola - instant Siteminder integration. Make sense?



          • #6
            If you _always_ knew the username was available from request.getHeader("sm_user"), you'd adopt a different strategy and make your "well known location" the request.getHeader. In other words, you'd take a look at how net.sf.acegisecurity.ui.HttpSessionIntegrationFilt er works. You'd write something similar and avoid needing to write any "authentication processing filters". Your acegisecurity.ui style filter would create an Authentication object each time at the start of the request, containing the username you obtained from the request. This would be placed into the ContextHolder (just like all ui filters do) and made null at the end of each request.

            Later on your AuthenticationDao would lookup the GrantedAuthority[]s that apply and return a populated Authentication object. The MethodSecurityInterceptor would cause the ContextHolder to be updated with a populated Authentication that contains the GrantedAuthority[]s.


            • #7
              One small question...


              I am new to Acegi but have now read the whole reference guide and looked at several demos and I can't find the answer to this simple question..

              I want to implement programmatic security- that is I want to access ContextHolder-->SecureContext-->Authentication (I think this is the correct path) in my code. I have Acegi setup and working fine for declarative security (authentication etc.) so my ContextHolder is populated and ready to go.

              My question is simple - how do I actually grab a reference to Context Holder? Have I missed something obvious (very likely)? In your replies to this thread you mention accessing the ContextHolder but nowhere is there an example code snippet on how to do this. Could you help me out by providing a few lines of code demonstrating how I can obtain a reference to ContextHolder (and hence the underlying Authentication instance) from any Spring bean or Tapestry component (I use Tapestry for my MVC layer)?



              • #8
                You can access the ContextHolder from anywhere using the static methods on the class. Alternatively, use the convenience method