1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application.viewstate;
20
21 import javax.faces.context.ExternalContext;
22 import javax.faces.context.FacesContext;
23
24 import org.apache.myfaces.application.StateCache;
25 import org.apache.myfaces.application.viewstate.token.ClientSideStateTokenProcessor;
26 import org.apache.myfaces.application.viewstate.token.StateTokenProcessor;
27 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
28 import org.apache.myfaces.shared.util.WebConfigParamUtils;
29
30 class ClientSideStateCacheImpl extends StateCache<Object, Object>
31 {
32
33
34
35
36
37
38 @JSFWebConfigParam(since="2.1.9, 2.0.15", defaultValue="0", group="state")
39 public static final String INIT_PARAM_CLIENT_VIEW_STATE_TIMEOUT =
40 "org.apache.myfaces.CLIENT_VIEW_STATE_TIMEOUT";
41 public static final Long INIT_PARAM_CLIENT_VIEW_STATE_TIMEOUT_DEFAULT = 0L;
42
43 private static final int STATE_PARAM = 0;
44 private static final int VIEWID_PARAM = 1;
45 private static final int TIMESTAMP_PARAM = 2;
46
47 private static final Object[] EMPTY_STATES = new Object[]{null, null};
48
49 private Long _clientViewStateTimeout;
50
51 private CsrfSessionTokenFactory csrfSessionTokenFactory;
52 private StateTokenProcessor stateTokenProcessor;
53
54 public ClientSideStateCacheImpl()
55 {
56 FacesContext facesContext = FacesContext.getCurrentInstance();
57
58 String csrfRandomMode = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
59 RANDOM_KEY_IN_CSRF_SESSION_TOKEN_PARAM,
60 RANDOM_KEY_IN_CSRF_SESSION_TOKEN_PARAM_DEFAULT);
61 if (RANDOM_KEY_IN_CSRF_SESSION_TOKEN_SECURE_RANDOM.equals(csrfRandomMode))
62 {
63 csrfSessionTokenFactory = new SecureRandomCsrfSessionTokenFactory(facesContext);
64 }
65 else
66 {
67 csrfSessionTokenFactory = new RandomCsrfSessionTokenFactory(facesContext);
68 }
69
70 stateTokenProcessor = new ClientSideStateTokenProcessor();
71 }
72
73 @Override
74 public Object saveSerializedView(FacesContext facesContext,
75 Object serializedView)
76 {
77
78
79
80 return encodeSerializedState(facesContext, serializedView);
81 }
82
83 @Override
84 public Object restoreSerializedView(FacesContext facesContext,
85 String viewId, Object viewState)
86 {
87 Object[] state = (Object[]) viewState;
88 long clientViewStateTimeout = getClientViewStateTimeout(facesContext.getExternalContext());
89
90 if (clientViewStateTimeout > 0L)
91 {
92 Long timeStamp = (Long) state[TIMESTAMP_PARAM];
93 if (timeStamp == null)
94 {
95
96 return null;
97 }
98 long passedTime = (System.currentTimeMillis() - timeStamp.longValue()) / 60000;
99
100 if (passedTime > clientViewStateTimeout)
101 {
102
103 return null;
104 }
105 }
106
107 String restoredViewId = (String) state[VIEWID_PARAM];
108
109 if (viewId != null && !viewId.equals(restoredViewId))
110 {
111
112 return null;
113 }
114
115
116 if (state[STATE_PARAM] == null)
117 {
118 return EMPTY_STATES;
119 }
120 else
121 {
122 Object serializedView = state[STATE_PARAM];
123 if (serializedView instanceof Object[] &&
124 ((Object[])serializedView).length == 2 &&
125 ((Object[])serializedView)[0] == null &&
126 ((Object[])serializedView)[1] == null)
127 {
128
129 return null;
130 }
131
132 return state[STATE_PARAM];
133 }
134 }
135
136 @Override
137 public Object encodeSerializedState(FacesContext facesContext,
138 Object serializedView)
139 {
140 Object[] state = null;
141
142 if (getClientViewStateTimeout(facesContext.getExternalContext()).longValue() > 0L)
143 {
144 state = new Object[3];
145 state[TIMESTAMP_PARAM] = System.currentTimeMillis();
146 }
147 else
148 {
149 state = new Object[2];
150 }
151
152 if (serializedView == null)
153 {
154 state[STATE_PARAM] = EMPTY_STATES;
155 }
156 else if (serializedView instanceof Object[] &&
157 ((Object[])serializedView).length == 2 &&
158 ((Object[])serializedView)[0] == null &&
159 ((Object[])serializedView)[1] == null)
160 {
161
162
163 state[STATE_PARAM] = null;
164 }
165 else
166 {
167 state[STATE_PARAM] = serializedView;
168 }
169
170 state[VIEWID_PARAM] = facesContext.getViewRoot().getViewId();
171
172 return state;
173 }
174
175 @Override
176 public boolean isWriteStateAfterRenderViewRequired(FacesContext facesContext)
177 {
178 return true;
179 }
180
181
182
183
184 protected Long getClientViewStateTimeout(ExternalContext context)
185 {
186 if (_clientViewStateTimeout == null)
187 {
188 _clientViewStateTimeout = WebConfigParamUtils.getLongInitParameter(
189 context, INIT_PARAM_CLIENT_VIEW_STATE_TIMEOUT,
190 INIT_PARAM_CLIENT_VIEW_STATE_TIMEOUT_DEFAULT);
191 if (_clientViewStateTimeout.longValue() < 0L)
192 {
193 _clientViewStateTimeout = 0L;
194 }
195 }
196 return _clientViewStateTimeout;
197 }
198
199 @Override
200 public String createCryptographicallyStrongTokenFromSession(FacesContext context)
201 {
202 return csrfSessionTokenFactory.createCryptographicallyStrongTokenFromSession(context);
203 }
204
205 @Override
206 public StateTokenProcessor getStateTokenProcessor(FacesContext context)
207 {
208 return stateTokenProcessor;
209 }
210 }