0

我正在尝试在 cq5 中实现注销 servlet,我需要从 cas 服务器和 cq5 注销我的用户。问题是我需要 servlet 从 cq5 注销然后重定向到 cas 注销页面,但是由于我使用响应来执行这两项操作,所以我得到了 IllegalStateException。

关于如何做到这一点的任何想法?

这是我的 servlet 代码:

import com.stuff.etc.*;

@Component( metatype = false)
@SlingServlet(
        methods = {"GET"},
        generateComponent = false        
)
@Service
public class MyLogoutServlet extends SlingAllMethodsServlet {   

    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
    private Authenticator authenticator;

    public static final String PAR_USER = "username";

    @Property(name = "sling.servlet.paths")
    public static final String SERVLET_PATH = "/system/mysite/logout";

    @Property(name = "sling.auth.requirements", propertyPrivate = true)
    //@SuppressWarnings("unused")
    private static final String[] AUTH_REQUIREMENT = { "-" + SERVLET_PATH };

    private static final Logger log = LoggerFactory.getLogger(CookieStoreUtil.class);  

    public static final String TOKEN_COOKIE_ID = "mysite_auth";

    private static final String LOGOUT_RESOURCE = "https://casurl.com/logout";

    @Reference
    private CryptoSupport cryptoSupport;

    @Reference
    private SlingSettingsService settingsService;

    @Override
    protected void doGet(SlingHttpServletRequest request,   SlingHttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter(PAR_USER);                       

        final Authenticator authenticator = this.authenticator;
        log.info(String.valueOf(authenticator==null));

        if(username != null) {
            if(log.isDebugEnabled()) {
                log.debug("Request to logout user: " + username);
            }
            request.removeAttribute(WSCAuthToken.TOKEN_ATTR_USER);
            WSCAuthToken token = getAuthToken(request, cryptoSupport);

            //if(token != null && token.isDebugMode()) {
            if(token != null) {
                token.setUser(null);
                token.resetAttributes();
                saveAuthCookie(request, response, cryptoSupport, token);

                CookieStoreUtil.resetStoreCookie(request, response, settingsService);               
                TokenCookie.setCookie(response, TOKEN_COOKIE_ID, "", -1, "/", null, false, request.isSecure());

                if (authenticator != null) {
                    try {
                        log.info("SIAMO QUI");
                        log.info("ANDIAMO QUI: "+request.getContextPath());
                        AbstractAuthenticationHandler.setLoginResourceAttribute(request, request.getContextPath());
                        authenticator.logout(request, response);
                    } catch (IllegalStateException ise) {
                        log.error("service: Response already committed, cannot logout");
                        return;
                    }
                } else {
                    log.error("service: Authenticator service missing, cannot logout");
                }

            } else {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED);        
            }                           
        }   else {  
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Username non specificato");     
        }
        response.sendRedirect(LOGOUT_RESOURCE);
        //response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }   

    public static WSCAuthToken getAuthToken(HttpServletRequest request, CryptoSupport cryptoSupport) {
        WSCAuthToken token = null;

        Object tokenAttr = request.getAttribute(TOKEN_COOKIE_ID);
        if ((tokenAttr instanceof WSCAuthToken)) {          
            return (WSCAuthToken)tokenAttr;
        }

        String cookie = TokenCookie.getCookie(request, TOKEN_COOKIE_ID);                            

        if (cookie != null) {
            String value;
            try {
                value = cryptoSupport.unprotect(cookie);
                token = WSCAuthToken.fromJSON(value);
            } catch (CryptoException e) {
                log.error("CryptoException getting token: " + e.getMessage());
            }           
        }
        return token;
    } 

    public static void saveAuthCookie(HttpServletRequest request, HttpServletResponse response, 
            CryptoSupport cryptoSupport, WSCAuthToken token) {

        try {           
            request.setAttribute(token.getCk(), token);
            String value = cryptoSupport.protect(token.toJSON());           
            TokenCookie.setCookie(response, TOKEN_COOKIE_ID, "\"" + value + "\"", -1, "/", null, true, request.isSecure());         
        } catch (CryptoException e) {
            log.error("CryptoException saving cookie", e);
        } catch (IOException e) {
            log.error("IOException saving cookie", e);
        }   
    }
}

错误日志: 02.08.2013 11:03:23.966 *ERROR* [127.0.0.1 [1375434203945] GET /system/sorgeniabpp/logout HTTP/1.1] org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught Throwable java.lang.IllegalStateException: response already committed

另一个问题是我什至无法从 CQ5 注销。我试图将我的 servlet 与 org.apache.sling.auth.core.impl.LogoutServlet 上实现的代码合并,但没有结果。

4

2 回答 2

0

尝试return 在重定向后添加语句,以便它停止向response.

  response.sendRedirect(LOGOUT_RESOURCE);
  return; 

服务器已经完成了响应头的写入,并且正在写入内容的主体,而您正在尝试向标头写入更多内容 - 当然它不能倒带。

于 2013-08-02T09:18:03.697 回答
0

即使在sendError之后,您也需要添加return语句(正如@suresh atta 告诉您的那样,您需要在重定向之后添加return语句)。 根据HttpServletResponse#sendRedirectHttpServletResponse#sendError

如果响应已经提交,则此方法会抛出 IllegalStateException。使用此方法后,应将响应视为已提交,不应写入。

所以在sendError之后也有 return 语句。

 response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
 return;

and

 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Username non specificato");
 return;

with this

 response.sendRedirect(LOGOUT_RESOURCE);
 return;

For more details about why you need to add return statement after redirect or sendError

于 2013-08-02T14:28:23.830 回答