· 9 years ago · Sep 20, 2016, 06:16 PM
1commit 92743563df6d6a3a32757ab9b85f7e18e96ab609
2Author: vcacioppo <vincent.cac@gmail.com>
3Date: Sun May 22 15:55:49 2016 -0400
4
5 not working yet
6
7diff --git a/sql/5.18.2016/preseed.sql b/sql/5.18.2016/preseed.sql
8index e7ccde7..55574bd 100644
9--- a/sql/5.18.2016/preseed.sql
10+++ b/sql/5.18.2016/preseed.sql
11@@ -1,7 +1,3 @@
12---
13--- PostgreSQL database dump
14---
15-
16 SET statement_timeout = 0;
17 SET lock_timeout = 0;
18 SET client_encoding = 'UTF8';
19@@ -11,16 +7,12 @@ SET client_min_messages = warning;
20
21 SET search_path = public, pg_catalog;
22
23---
24--- Data for Name: account; Type: TABLE DATA; Schema: public; Owner: Market
25---
26
27-INSERT INTO account VALUES (1, '2016-05-15 22:52:05.94', NULL, NULL, NULL, '100', NULL, 'btc', 1);
28+INSERT INTO exchangeuser VALUES (1, '2016-05-15 22:52:05.94', NULL, NULL, NULL, 'test');
29
30
31---
32--- Data for Name: address; Type: TABLE DATA; Schema: public; Owner: Market
33---
34+INSERT INTO account VALUES (1, '2016-05-15 22:52:05.94', NULL, NULL, NULL, '100', NULL, 'btc', 1);
35+
36
37 INSERT INTO address VALUES (1, '2016-05-15 14:55:04', NULL, NULL, NULL, 'mnd5rhkosopNTCv9rPD3wxJiY8hfq4S2Ro', 1);
38 INSERT INTO address VALUES (2, '2016-05-15 14:55:04', NULL, NULL, NULL, 'mm86CdB5WE75CfMjfP4JeT1kispdyrdoU8', NULL);
39@@ -221,17 +213,4 @@ INSERT INTO address VALUES (196, '2016-05-15 14:55:04', NULL, NULL, NULL, 'n49T6
40 INSERT INTO address VALUES (197, '2016-05-15 14:55:04', NULL, NULL, NULL, 'mq5R1RpBFWj6mJn5WM9PUyEAqk8NwB7FZg', NULL);
41 INSERT INTO address VALUES (198, '2016-05-15 14:55:04', NULL, NULL, NULL, 'mtQHMN9zq5UTGwWBbJXetJdHWRfYVeLPV8', NULL);
42 INSERT INTO address VALUES (199, '2016-05-15 14:55:04', NULL, NULL, NULL, 'mtuWKzJFkUBLovmSMKv8tFiZLxsFwmSXkP', NULL);
43-INSERT INTO address VALUES (200, '2016-05-15 14:55:04', NULL, NULL, NULL, 'n2eRqvNkAFpz2qDaPKDuVVQYs9dtiU6JeX', NULL);
44-
45-
46---
47--- Data for Name: exchangeuser; Type: TABLE DATA; Schema: public; Owner: Market
48---
49-
50-INSERT INTO exchangeuser VALUES (1, '2016-05-15 22:52:05.94', NULL, NULL, NULL, 'test');
51-
52-
53---
54--- PostgreSQL database dump complete
55---
56-
57+INSERT INTO address VALUES (200, '2016-05-15 14:55:04', NULL, NULL, NULL, 'n2eRqvNkAFpz2qDaPKDuVVQYs9dtiU6JeX', NULL);
58\ No newline at end of file
59diff --git a/src/main/java/com/market/order/OrderAPI.java b/src/main/java/com/market/order/OrderAPI.java
60index 2e9c471..a56bbad 100644
61--- a/src/main/java/com/market/order/OrderAPI.java
62+++ b/src/main/java/com/market/order/OrderAPI.java
63@@ -20,7 +20,7 @@ import java.util.logging.Logger;
64 * Created by milenko000 on 4/24/2016.
65 */
66 @RestController
67-@RequestMapping("/v1")
68+@RequestMapping(value = {"/v1", "/api/v1"})
69 @EnableAutoConfiguration
70 public class OrderAPI {
71
72diff --git a/src/main/java/com/market/security/CustomDigestAuthenticationFilter.java b/src/main/java/com/market/security/CustomDigestAuthenticationFilter.java
73new file mode 100644
74index 0000000..1cb1544
75--- /dev/null
76+++ b/src/main/java/com/market/security/CustomDigestAuthenticationFilter.java
77@@ -0,0 +1,146 @@
78+package com.market.security;
79+
80+import com.google.common.base.Strings;
81+import org.slf4j.Logger;
82+import org.slf4j.LoggerFactory;
83+import org.springframework.beans.factory.annotation.Autowired;
84+import org.springframework.security.authentication.AbstractAuthenticationToken;
85+import org.springframework.security.authentication.AuthenticationServiceException;
86+import org.springframework.security.core.Authentication;
87+import org.springframework.security.core.AuthenticationException;
88+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
89+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
90+
91+import javax.crypto.Mac;
92+import javax.crypto.SecretKey;
93+import javax.crypto.spec.SecretKeySpec;
94+import javax.servlet.FilterChain;
95+import javax.servlet.ServletException;
96+import javax.servlet.ServletRequest;
97+import javax.servlet.ServletResponse;
98+import javax.servlet.http.HttpServletRequest;
99+import javax.servlet.http.HttpServletResponse;
100+import javax.xml.bind.DatatypeConverter;
101+import java.io.IOException;
102+import java.security.InvalidKeyException;
103+import java.security.NoSuchAlgorithmException;
104+import java.text.MessageFormat;
105+
106+/**
107+ * Created by milenko000 on 5/21/2016.
108+ */
109+public class CustomDigestAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
110+
111+ private static final Logger logger = LoggerFactory.getLogger(CustomTokenAuthenticationFilter.class);
112+ private static final String HEADER_API_KEY = "X-TFX-APIKEY";
113+ private static final String HEADER_PAYLOAD = "X-TFX-PAYLOAD";
114+ private static final String HEADER_SIGNATURE = "X-TFX-SIGNATURE";
115+ private static final String FILTER_APPLIED = "CustomDigestAuthenticationFilter.APPLIED";
116+
117+
118+ @Autowired
119+ private SecurityRepository securityRepository;
120+
121+ public CustomDigestAuthenticationFilter(String defaultFilterProcessesUrl) {
122+ super(defaultFilterProcessesUrl);
123+ super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl));
124+ super.setAuthenticationManager(new NoOpAuthenticationManager());
125+ super.setAuthenticationSuccessHandler(new TokenSimpleUrlAuthenticationSuccessHandler());
126+ }
127+
128+ /**
129+ * Attempt to authenticate request - basically just pass over to another method to authenticate request headers
130+ */
131+ @Override
132+ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
133+ String apiKey = request.getHeader(HEADER_API_KEY);
134+ String payLoad = request.getHeader(HEADER_PAYLOAD);
135+ String signature = request.getHeader(HEADER_SIGNATURE);
136+// String body = "";
137+// if ("POST".equals(request.getMethod())) {
138+// body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
139+// }
140+ AbstractAuthenticationToken userAuthenticationToken = authUserByDigest(apiKey, payLoad, signature);
141+ if (userAuthenticationToken == null) {
142+ throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
143+ }
144+ return userAuthenticationToken;
145+ }
146+
147+
148+ /**
149+ * authenticate the user based on digest
150+ *
151+ * @return
152+ */
153+ private AbstractAuthenticationToken authUserByDigest(String apiKey, String payLoad, String signature) {
154+ if (Strings.isNullOrEmpty(apiKey) || Strings.isNullOrEmpty(payLoad) || Strings.isNullOrEmpty(signature)) {
155+ return null;
156+ }
157+
158+ SecurityPrincipal securityPrincipal = securityRepository.findByClientId(apiKey);
159+ if (securityPrincipal == null) {
160+ return null;
161+ }
162+
163+ if (!validateDigest(payLoad, signature, securityPrincipal.getPrivateKey())) {
164+ return null;
165+ }
166+
167+ AbstractAuthenticationToken authToken = new CustomAuthenticationToken(null, securityPrincipal);
168+ try {
169+ return authToken;
170+ } catch (Exception e) {
171+ logger.error("Authenticate user by token error: ", e);
172+ }
173+ return authToken;
174+ }
175+
176+ private boolean validateDigest(String payLoad, String signature, String secret) {
177+ if (Strings.isNullOrEmpty(secret)) {
178+ return false;
179+ }
180+
181+ boolean rtn = false;
182+ byte[] data;
183+ byte[] rawHmac;
184+ try {
185+ SecretKey secretKey = null;
186+
187+ byte[] keyBytes = secret.getBytes();
188+ secretKey = new SecretKeySpec(keyBytes, "HmacSHA384");
189+
190+ Mac mac = Mac.getInstance("HmacSHA384");
191+ mac.init(secretKey);
192+
193+ data = payLoad.getBytes();
194+ rawHmac = mac.doFinal(data);
195+
196+ String encryptedSig = DatatypeConverter.printHexBinary(rawHmac);
197+
198+ if (signature.equals(encryptedSig)) {
199+ rtn = true;
200+ }
201+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
202+ logger.error("Error Verifying signature ", e);
203+ throw new RuntimeException("Error Verfiying signature ");
204+ }
205+
206+ return rtn;
207+ }
208+
209+ @Override
210+ public void doFilter(ServletRequest req, ServletResponse res,
211+ FilterChain chain) throws IOException, ServletException {
212+
213+ Object filterApplied = req.getAttribute(FILTER_APPLIED);
214+ if (filterApplied != null) {
215+ // ensure that filter is only applied once per request
216+ chain.doFilter(req, res);
217+ return;
218+ }
219+ req.setAttribute(FILTER_APPLIED, Boolean.TRUE);
220+ super.doFilter(req, res, chain);
221+ }
222+
223+}
224diff --git a/src/main/java/com/market/security/CustomTokenAuthenticationFilter.java b/src/main/java/com/market/security/CustomTokenAuthenticationFilter.java
225index f021009..b2a26bd 100644
226--- a/src/main/java/com/market/security/CustomTokenAuthenticationFilter.java
227+++ b/src/main/java/com/market/security/CustomTokenAuthenticationFilter.java
228@@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletRequest;
229 import javax.servlet.http.HttpServletResponse;
230 import java.io.IOException;
231 import java.text.MessageFormat;
232-import java.util.stream.Collectors;
233
234 public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
235
236@@ -47,10 +46,6 @@ public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProce
237 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
238 String token = request.getHeader(HEADER_SECURITY_TOKEN);
239 String clientId = request.getHeader(HEADER_SECURITY_CLIENT_ID);
240- String body = "";
241- if ("POST".equals(request.getMethod())) {
242- body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
243- }
244 AbstractAuthenticationToken userAuthenticationToken = authUserByToken(token, clientId);
245 if(userAuthenticationToken == null) {
246 throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
247diff --git a/src/main/java/com/market/security/SecurityConfig.java b/src/main/java/com/market/security/SecurityConfig.java
248index 3a2d831..22fbc02 100644
249--- a/src/main/java/com/market/security/SecurityConfig.java
250+++ b/src/main/java/com/market/security/SecurityConfig.java
251@@ -1,7 +1,9 @@
252 package com.market.security;
253
254+import org.springframework.beans.factory.annotation.Autowired;
255 import org.springframework.context.annotation.Bean;
256 import org.springframework.context.annotation.Configuration;
257+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
258 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
259 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
260 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
261@@ -10,26 +12,54 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
262 /**
263 * Created by alvin on 5/1/16.
264 */
265-@Configuration
266 @EnableWebSecurity
267 public class SecurityConfig extends WebSecurityConfigurerAdapter {
268
269- @Override
270- protected void configure(HttpSecurity http) throws Exception {
271+ @Autowired
272+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
273+ auth
274+ .inMemoryAuthentication()
275+ .withUser("user").password("password").roles("USER").and()
276+ .withUser("admin").password("password").roles("USER", "ADMIN");
277+ }
278+
279+ @Configuration
280+ public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
281+ protected void configure(HttpSecurity http) throws Exception {
282+ http
283+ .csrf().disable()
284+ .antMatcher("/api/**")
285+ .authorizeRequests()
286+ .anyRequest().hasRole("ExchangeUser")
287+ .and()
288+ .addFilterBefore(authenticationTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
289+ }
290
291- http
292- .csrf().disable()
293- .authorizeRequests().antMatchers("/", "/home", "/api/**").permitAll()//.and()
294- //.authorizeRequests().antMatchers("/api/**").hasRole("API").and()
295- //.addFilterBefore(authenticationTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
296- ;
297
298+ @Bean
299+ public CustomDigestAuthenticationFilter authenticationTokenProcessingFilter() {
300+ return new CustomDigestAuthenticationFilter("/v1/**");
301+ }
302 }
303
304-// @Bean
305-// public CustomTokenAuthenticationFilter authenticationTokenProcessingFilter(){
306-// return new CustomTokenAuthenticationFilter("/api/**");
307-// }
308+ @Configuration
309+ public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
310+
311+ @Override
312+ protected void configure(HttpSecurity http) throws Exception {
313+ http
314+ .csrf()
315+ .disable()
316+ .authorizeRequests().antMatchers("/").permitAll().and()
317+ .authorizeRequests().antMatchers("/v1/**").hasRole("ExchangeUser").and()
318+ .addFilterBefore(authenticationTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
319+ }
320
321+
322+ @Bean
323+ public CustomTokenAuthenticationFilter authenticationTokenProcessingFilter() {
324+ return new CustomTokenAuthenticationFilter("/v1/**");
325+ }
326+ }
327 }