문제

I have a JSF/Primefaces application.

I now need to support Kerberos authentication and there are multiple components that will use the Kerberos credentials (database connections, app connections etc.).

What I need to do is wrap every operation that needs credentials with code like this:

Subject.doAs(loginContext.getSubject(), new PrivilegedExceptionAction<Long>() {
        @Override
        public Long run() throws UnknownHostException {
            // Perform operation on database for example
            ...
        }
});

But there are thousands of such places I would need to wrap.

Instead, what I really want to do is wrap the entry point that will cover all operations in the system.

I am thinking of subclassing FacesServlet and just have a service method that wraps the superclasses's service inside this doAs.

Is that the right way to do something like this or is there a more appropriate JSF pattern? If anyone has an example of doing this and doesn't mind sharing the relevant code, much appreciated.

Edit - I now saw that FacesServlet is a final class so I can;t subclass it. But I can still wrap it - with an embedded instance of a FacesServlet. But I'm sure I have to get the lifecycle right - has anyone done this before and can share experience?

도움이 되었습니까?

해결책

You can do it by adding a filter for all your data/jsf requests . The filter would verify if the request has Kerberos key/certificate before forwarding the request.

If you want to authenticate your services then you can use something like Spring AOP and add Advise that covers your services

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class KerberosAspectJoinPoint { 

    @Before("execution(public void com.service...*(*))")
    public void kerberosAdvice(JoinPoint joinPoint){
        //Verify Authentication and throw error; 
    }
}

or you can do selective by creating annotation and adding the annotation to your service methods you want to authenticate ,

public @interface VerifyAuth {

}

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class KerberosAspectJoinPoint {

    @Before("@annotation(com.test.VerifyAuth)")
    public void myAdvice(){
        //Verify Authentication and throw error; 
    }
}

But if you plan to cover everything in the application then validating in the filter seems like a good place for web app.

class LoginFilter implements Filter  {


      public void doFilter(ServletRequest request, 
               ServletResponse response, FilterChain chain) throws      
               IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        Subject.doAs(lc.getSubject(), new LoginAction(chain, 
             request,response));

    }
}


class LoginAction implements java.security.PrivilegedAction {
    private HttpServletRequest request;
    private HttpServletResponse response;
    private FilterChain chain;

    public LoginAction(HttpServletRequest request, 
      HttpServletResponse response, FilterChain chain) {
    this.request = request;
    this.response = response;
    this.chain = chain;
    }

    public Object run() {
    doForward(request, response, chain);
    return null;
    }

    private static void doForward (HttpServletRequest request, 
       HttpServletResponse response, FilterChain chain)     {
    chain.doFilter(request, response);
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top