2014-03-27 3 views
4

jsf에서 프라임 스 페이스로 몇 가지 기본 푸시 기능을 구현하려고했습니다. 나는 카운터 예제 인 http://www.primefaces.org/showcase-labs/push/counter.jsf을 사용했다. 기본적으로 공유 카운터를 증가시키는 버튼입니다. 이 예제를 실행하는 경우 난 항상이 오류 :JSF "Mac에서 오류를 확인하지 못했습니다!"

ERROR: MAC did not verify! 

나의 이해는 맥이 모든 세션을 생성하고 소스가 (내가 생각하는) 변경되지 않았 음을 확인하기 위해 각각의 수신 메시지에 따라 선택되어 있는지입니다. 나는이의 원인을 찾을 수 없어와 같은 다른 스레드에서 보았다 :

ERROR: MAC did not verify! PrimeFaces

JSF: Mojarra 2.1 to 2.2 migration causing ViewExpiredException

불행하게도 이러한 해결되지 내 문제. 둘 다 내가 얻지 못하는 ViewExpiredException에 의해 발생하는 것 같습니다. 나는 그것을 중지 발견 한 유일한 것은 web.xml 파일에 클라이언트에서 서버로 상태 저장 방법을 변경하는 것입니다 : 더 이상 공유이 카운터를 수행 할 때 그러나

<param-name>javax.faces.STATE_SAVING_METHOD</param-name> 
<param-value>client</param-value> 

하지만 사용자 당 것으로 보인다, 그건 내가 원하는 바가 아니야. 나의 궁극적 인 목표는 chatroom을 구현하는 것인데, 대부분 chatroom을 구현하는 것이지만 바로 지금은 확장 성이 좋지 않은 짧은 폴링을 사용한다. primefaces 푸시를 보았을 때 이상적이라고 생각했지만 사용하는 데 어려움을 겪어 왔습니다.

여러 웹 서버 (Tomcat, Jetty 및 Glassfish)를 사용해 보았으며 다른 버전의 JSF (Mojarra) 및 primefaces (3.4 및 4.0) 버전을 사용해 보았습니다. 여러 브라우저와 여러 대의 컴퓨터에서 테스트 해 보았습니다. 때때로 오류가 발생하기 전에 카운터를 몇 번 증분 할 수 있습니다. 때로는 바로 발생합니다. 예외 나 서브 디렉토리 오류가 발생하지 않으며 모든 것이 컴파일됩니다. 이전에 다른 프로젝트에서이 오류가 발생했음을 언급하고자하지만 서버를 다시 시작한 후에 사라졌습니다. primefaces를 사용하면 항상 발생합니다. 어떤 도움을 주시면 감사하겠습니다.

편집

MAC 오류를 피하기 위해 web.xml 파일에서 서버에 저장 상태를 떠나, 내가 공유 카운터가 동일한 시스템에서 브라우저별로 작동 것으로 나타났습니다. 여러 개의 탭이나 창을 가지고있는 경우 하나의 카운터를 모두 업데이트하면 모든 것이 업데이트됩니다. 브라우저 간에는 작동하지 않지만 파이어 폭스의 카운터 변경은 크롬이나 IE 또는 다른 방식으로 반영되지 않습니다. 별도의 컴퓨터 두 대에있는 경우에도 반영되지 않습니다. 이것이 도움이되는지 나는 모른다. 그러나 나는 그것을 언급 할 것이라고 생각했다.

예에서 콩은 세션이 응용 프로그램 범위에 내가 그것을 변경 범위는 것을 알아 차리지 후 편집

. 물론 세션 범위는 모든 브라우저가 자체 복사본을 가지고 있음을 의미합니다. 이제 변경 사항은 브라우저와 컴퓨터에 반영됩니다. 원래의 문제로 돌아가서, 나는 여전히 서버에 저장 상태를 변경하면 MAC 오류를 수정하는 이유와 그 의미가 무엇인지 알고 싶습니다. 이제는 서버가 클라이언트가 아닌 각 세션의 뷰 상태를 유지해야한다고 가정합니다. 서버에 저장 상태를 설정하면 읽은 내용에서 만료 된 예외보기를 확인할 수 없거나 사용자가 이미 너무 많은 경우보기를 만들지 못하도록하는 것이 맞습니까?

+0

복제본마다 클라이언트 상태 저장 비밀 키를 구성해야합니다. 또는 서버 클러스터에서 실행중인 경우 고정 노드를 사용하고 있는지 확인해야합니다. – BalusC

답변

0

응용 프로그램이 ViewExpiredException 쉽게 처리 할 수 ​​있습니다 의존성 문제가있는 것 같은데, 그것은 handle ViewExpiredException

전체 구성 JSF 프로젝트 예를 JSF2.2 frontend

+0

첫 번째 링크가 고장났습니다. 작동 링크를 추가하십시오. – aName

-4

ByteArrayGuard 클래스는 무작위로 ERROR "출력하는 문제가되지 않습니다 : MAC은 확인하지 않았다! " 오류 콘솔에 메시지. 이는 클라이언트 측 viewstate 암호화가 사용 가능하고 여러 클라이언트가 서버에 대해 실행 중일 때만 발생합니다.

그래서 당신은 ...에 대한 참조를 얼굴 자바 서버에

/* 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 
* 
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved. 
* 
* The contents of this file are subject to the terms of either the GNU 
* General Public License Version 2 only ("GPL") or the Common Development 
* and Distribution License("CDDL") (collectively, the "License"). You 
* may not use this file except in compliance with the License. You can 
* obtain a copy of the License at 
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 
* or packager/legal/LICENSE.txt. See the License for the specific 
* language governing permissions and limitations under the License. 
* 
* When distributing the software, include this License Header Notice in each 
* file and include the License file at packager/legal/LICENSE.txt. 
* 
* GPL Classpath Exception: 
* Oracle designates this particular file as subject to the "Classpath" 
* exception as provided by Oracle in the GPL Version 2 section of the License 
* file that accompanied this code. 
* 
* Modifications: 
* If applicable, add the following below the License Header, with the fields 
* enclosed by brackets [] replaced by your own identifying information: 
* "Portions Copyright [year] [name of copyright owner]" 
* 
* Contributor(s): 
* If you wish your version of this file to be governed by only the CDDL or 
* only the GPL Version 2, indicate your decision by adding "[Contributor] 
* elects to include this software in this distribution under the [CDDL or GPL 
* Version 2] license." If you don't indicate a single choice of license, a 
* recipient has the option to distribute your version of this file under 
* either the CDDL, the GPL Version 2 or to extend the choice of license to 
* its licensees as provided above. However, if you add GPL Version 2 code 
* and therefore, elected the GPL Version 2 license, then the option applies 
* only if the new code is made subject to such option by the copyright 
* holder. 
*/ 

package com.sun.faces.renderkit; 

import com.sun.faces.util.FacesLogger; 
import java.security.SecureRandom; 
import java.util.Arrays; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.crypto.Cipher; 
import javax.crypto.KeyGenerator; 
import javax.crypto.Mac; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.IvParameterSpec; 
import javax.faces.FacesException; 

/** 
* <p>This utility class is to provide both encryption and 
* decryption <code>Ciphers</code> to <code>ResponseStateManager</code> 
* implementations wishing to provide encryption support.</p> 
* 
* <p>The algorithm used to encrypt byte array is AES with CBC.</p> 
* 
* <p>Original author Inderjeet Singh, J2EE Blue Prints Team. Modified to suit JSF 
* needs.</p> 
*/ 
public final class ByteArrayGuard { 


    // Log instance for this class 
    private static final Logger LOGGER = FacesLogger.RENDERKIT.getLogger(); 

    private static final int MAC_LENGTH = 32; 
    private static final int KEY_LENGTH = 128; 
    private static final int IV_LENGTH = 16; 

    private static final String KEY_ALGORITHM = "AES"; 
    private static final String CIPHER_CODE = "AES/CBC/PKCS5Padding"; 
    private static final String MAC_CODE = "HmacSHA256"; 
    private SecretKey sk; 

    // ------------------------------------------------------------ Constructors 

    public ByteArrayGuard() { 

     try { 
      setupKeyAndMac(); 
     } catch (Exception e) { 
      if (LOGGER.isLoggable(Level.SEVERE)) { 
       LOGGER.log(Level.SEVERE, 
          "Unexpected exception initializing encryption." 
          + " No encryption will be performed.", 
          e); 
      } 
      System.err.println("ERROR: Initializing Ciphers"); 
     } 
    } 

    // ---------------------------------------------------------- Public Methods  


    /** 
    * This method: 
    * Encrypts bytes using a cipher. 
    * Generates MAC for intialization vector of the cipher 
    * Generates MAC for encrypted data 
    * Returns a byte array consisting of the following concatenated together: 
    *  |MAC for cnrypted Data | MAC for Init Vector | Encrypted Data | 
    * @param bytes The byte array to be encrypted. 
    * @return the encrypted byte array. 
    */ 
    public byte[] encrypt(byte[] bytes) { 
     byte[] securedata = null; 
     try { 
      // Generate IV 
      SecureRandom rand = new SecureRandom(); 
      byte[] iv = new byte[16]; 
      rand.nextBytes(iv); 
      IvParameterSpec ivspec = new IvParameterSpec(iv); 
      Cipher encryptCipher = Cipher.getInstance(CIPHER_CODE); 
      encryptCipher.init(Cipher.ENCRYPT_MODE, sk, ivspec); 
      Mac encryptMac = Mac.getInstance(MAC_CODE); 
      encryptMac.init(sk); 
      encryptMac.update(iv); 
      // encrypt the plaintext 
      byte[] encdata = encryptCipher.doFinal(bytes); 
      byte[] macBytes = encryptMac.doFinal(encdata); 
      byte[] tmp = concatBytes(macBytes, iv); 
      securedata = concatBytes(tmp, encdata); 
     } catch (Exception e) { 
      if (LOGGER.isLoggable(Level.SEVERE)) { 
       LOGGER.log(Level.SEVERE, 
          "Unexpected exception initializing encryption." 
          + " No encryption will be performed.", 
          e); 
      } 
      return null; 
     } 
     return securedata; 
    } 

    /** 
    * This method decrypts the provided byte array. 
    * The decryption is only performed if the regenerated MAC 
    * is the same as the MAC for the received value. 
    * @param bytes Encrypted byte array to be decrypted. 
    * @return Decrypted byte array. 
    */ 
    public byte[] decrypt(byte[] bytes) { 
     try { 
      // Extract MAC 
      byte[] macBytes = new byte[MAC_LENGTH]; 
      System.arraycopy(bytes, 0, macBytes, 0, macBytes.length); 

      // Extract IV 
      byte[] iv = new byte[IV_LENGTH]; 
      System.arraycopy(bytes, macBytes.length, iv, 0, iv.length); 

      // Extract encrypted data 
      byte[] encdata = new byte[bytes.length - macBytes.length - iv.length]; 
      System.arraycopy(bytes, macBytes.length + iv.length, encdata, 0, encdata.length); 

      IvParameterSpec ivspec = new IvParameterSpec(iv); 
      Cipher decryptCipher = Cipher.getInstance(CIPHER_CODE); 
      decryptCipher.init(Cipher.DECRYPT_MODE, sk, ivspec); 

      // verify MAC by regenerating it and comparing it with the received value 
      Mac decryptMac = Mac.getInstance(MAC_CODE); 
      decryptMac.init(sk); 
      decryptMac.update(iv); 
      decryptMac.update(encdata); 
      byte[] macBytesCalculated = decryptMac.doFinal(); 
      if (Arrays.equals(macBytes, macBytesCalculated)) { 
       // continue only if the MAC was valid 
       // System.out.println("Valid MAC found!"); 
       byte[] plaindata = decryptCipher.doFinal(encdata); 
       return plaindata; 
      } else { 
       System.err.println("ERROR: MAC did not verify!"); 
       return null; 
      } 
     } catch (Exception e) { 
      System.err.println("ERROR: Decrypting:"+e.getCause()); 
      return null; // Signal to JSF runtime 
     } 
    } 

    // --------------------------------------------------------- Private Methods 

    /** 
    * Generates secret key. 
    * Initializes MAC(s). 
    */ 
    private void setupKeyAndMac() { 

     try { 
      KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM); 
      kg.init(KEY_LENGTH); // 256 if you're using the Unlimited Policy Files 
      sk = kg.generateKey(); 

     } catch (Exception e) { 
      throw new FacesException(e); 
     } 
    } 

    /** 
    * This method concatenates two byte arrays 
    * @return a byte array of array1||array2 
    * @param array1 first byte array to be concatenated 
    * @param array2 second byte array to be concatenated 
    */ 
    private static byte[] concatBytes(byte[] array1, byte[] array2) { 
     byte[] cBytes = new byte[array1.length + array2.length]; 
     try { 
      System.arraycopy(array1, 0, cBytes, 0, array1.length); 
      System.arraycopy(array2, 0, cBytes, array1.length, array2.length); 
     } catch(Exception e) { 
      throw new FacesException(e); 
     } 
     return cBytes; 
    }  
} 

을 그 클래스를 변경하고이 항아리를 다시로드해야합니다. JSF_REFERENCE

+2

이것은 해결책이 아닙니다. 이것은 예상치 못한 해결 방법입니다. – BalusC

관련 문제