CAS Single Sign parse the source code [client]

cas 3.5.3 + spring boot server set up integrated analog login + shiro (shiro does not modify the existing authentication framework) . Because we belong to the suppliers, so some customers there will need to take the other side of the CAS, so there is no direct integration mode shiro and cas, if this is the case, you can refer to: https: //blog.csdn.net/catoop/article / details / 50534006.

Cas Client There are four main core filter:

l  AuthenticationFilter

l  TicketValidationFilter

l  HttpServletRequestWrapperFilter

l  AssertionThreadLocalFilter

Their role is explained as follows:

AuthenticationFilter

AuthenticationFilter used to intercept all requests to determine whether the user must be authenticated by Cas Server, if required will jump to the login page of Cas Server. If no login authentication, the request will continue down the implementation.

     AuthenticationFilter two users must specify parameter is used to specify a Cas Server login address casServerLoginUrl , and the other is used to specify the authentication is successful need to jump address serverName or Service . service and only need to specify a serverName it. When both are specified, the service parameters will have a higher priority parameter values specified service is about to prevail. the difference is that the service and serverName service specifies a certain URL, it will jump to the exact URL specified service after successful authentication; serverName is used to specify the host name, the format {protocol}: {hostName} : {port}, such as: https: // localhost: 8443, when the specified time is serverName, AuthenticationFilter it will be appended to the current request URI, and the corresponding query parameters to construct a determined URL, such as designated serverName after the jump address: "http // localhost", while the current request URI is "/ app", the query parameter is "a = b & b = c ", then the corresponding authentication is successful will be "http: // localhost / app? a = b & b = c " .

In addition to the above parameters that must be specified, AuthenticationFilter optional parameters can also be specified as follows:

L   renew : renew when specified is true, when the Cas Server please bring the parameter "renew = true", the default is false.

L   gateway : Specifies the gateway is true, at the end of the parameter request Cas Server "gateway = true", the default is false.

L   artifactParameterName : Specifies the name of the ticket corresponding to the request parameters, default ticket.

L   serviceParameterName : service request corresponding to the specified parameter name, default service.

 

TicketValidationFilter

After the authentication request through AuthenticationFilter, if the request carries the parameters of the ticket is to be carried by the ticket verify TicketValidationFilter. TicketValidationFilter collectively just the ticket validation Filter this type, which does not correspond to a particular type of Cas Client. Cas Client There are several authentication ticket of Filter, are inherited from AbstractTicketValidationFilter, their validation logic is the same, there AbstractTicketValidationFilter achieve, except that TicketValidator use is not the same. The default is Cas10TicketValidationFilter.

Optional parameters include:

L   redirectAfterValidation  : Indicates whether authentication is passed again to jump to the URL, but no arguments ticket, the default is true.

L   useSession  : After successful authentication ticket will generate a Assertion object useSession if true, the object is to store the Session. If false, is required for each request needs to carry the ticket to verify, apparently useSession is false is true with redirectAfterValidation conflict. The default is true.

l exceptionOnValidationFailure: express ticket after validation fails need to throw an exception, the default is true.

L   Renew : when the value is true transmits "renew = true" to Cas Server, default is false.

 

HttpServletRequestWrapperFilter

Assertion CasHttpServletRequestWrapper HttpServletRequestWrapperFilter objects for each request corresponding to its internal HttpServletRequest package defined, the package prior to use in Session class or request rewrite the HttpServletRequest getUserPrincipal (), getRemoteUser () and the isUserInRole () method. This can be very convenient to obtain information about the user from the HttpServletRequest in our application.

 

AssertionThreadLocalFilter

AssertionThreadLocalFilter for the convenience of users to access Assertion objects elsewhere in the application, it will store the current Assertion objects to the current thread variable, then the future users can obtain the current thread variable Assertion from anywhere in the program, no longer from or request parsing Session in. The thread variable is held by the AssertionHolder, getAssertion when we get the current Assertion only need AssertionHolder's () method to get to, such as:

   Assertion assertion = AssertionHolder.getAssertion();

 

cas client / shiro filter order, the case of an integrated cas, cas client always the first filter.
# doFilter org.jasig.cas.client.validation.AbstractTicketValidationFilter
    org.jasig.cas.client.util.CommonUtils # safeGetParameter
org.jasig.cas.client.authentication.AuthenticationFilter # doFilter - Here modify the source code, get the assertion, and after empty need to determine whether the token exists and is valid, if it exists and is valid, explanation has been logged, then directly back
    org.jasig.cas.client.util.CommonUtils # constructRedirectUrl 
    javax.servlet.http.HttpServletResponse # sendRedirect - this when the request went to CAS

And finally into shiro filter UserFilter.isAccessAllowed

 

Because after userfilter inside standard cas login, the user can get current information through UserPrincipal, but when we are clustered mode because of the time directly AuthenticationFilter # doFilter interception return, and without explicitly set, naturally took no to, servletrequest does not provide access to the settings of UserPrincipal, cas of org.jasig.cas.client.validation.Cas20ServiceTicketValidator # parseResponseFromServer is created, but org.jasig.cas.client.validation.Cas20ServiceTicketValidator # customParseResponse implementation body is empty . as follows:

protected final Assertion parseResponseFromServer(final String response) throws TicketValidationException {
        final String error = XmlUtils.getTextForElement(response,
                "authenticationFailure");

        if (CommonUtils.isNotBlank(error)) {
            throw new TicketValidationException(error);
        }

        final String principal = XmlUtils.getTextForElement(response, "user");
        final String proxyGrantingTicketIou = XmlUtils.getTextForElement(response, "proxyGrantingTicket");
        final String proxyGrantingTicket = this.proxyGrantingTicketStorage != null ? this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou) : null;

        if (CommonUtils.isEmpty(principal)) {
            throw new TicketValidationException("No principal was found in the response from the CAS server.");
        }

        final Assertion assertion;
        final Map<String,Object> attributes = extractCustomAttributes(response);
        if (CommonUtils.isNotBlank(proxyGrantingTicket)) {
            final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes, proxyGrantingTicket, this.proxyRetriever);
            assertion = new AssertionImpl(attributePrincipal);
        } else {
            assertion = new AssertionImpl(new AttributePrincipalImpl(principal, attributes));
        }

        customParseResponse(response, assertion);

        return assertion;
    }

stackoverflow also never found. as follows:

https://stackoverflow.com/questions/25885747/when-and-where-java-security-set-userprincipal

https://docs.oracle.com/javase/7/docs/jre/api/security/jaas/spec/com/sun/security/auth/UserPrincipal.html

At this point UserPrincipal If necessary, the need to rewrite their own by HttpServletRequestWrapperFilter, as follows:

    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
        final AttributePrincipal principal = retrievePrincipalFromSessionOrRequest(servletRequest);

        filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal), servletResponse);
    }

    protected AttributePrincipal retrievePrincipalFromSessionOrRequest(final ServletRequest servletRequest) {
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpSession session = request.getSession(false);
        final Assertion assertion = (Assertion) (session == null ? request.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));

        return assertion == null ? null : assertion.getPrincipal();
    }

In this case, shiro UserFilter which can pass

AttributePrincipal principal = (AttributePrincipal)((HttpServletRequest) request).getUserPrincipal();

To get information of the logged-on user.

 

Guess you like

Origin www.cnblogs.com/zhjh256/p/11689785.html