From cd16757f2cd963749850d6f8897381a8b7a849ef Mon Sep 17 00:00:00 2001
From: fengxiang <110431245@qq.com>
Date: Thu, 01 Feb 2018 15:09:43 +0800
Subject: [PATCH] 安全模块
---
src/main/java/com/moral/security/CustomCorsFilter.java | 33 +
src/main/java/com/moral/config/MvcConfiguration.java | 6
src/main/webapp/js/moralmap.js | 30
src/main/java/com/moral/security/model/token/JwtTokenFactory.java | 93 +++
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java | 53 +
src/main/java/com/moral/mapper/MonitorPointMapper.java | 2
src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java | 84 ++
src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java | 29
src/main/java/com/moral/security/common/ErrorCode.java | 27
src/main/java/com/moral/service/DeviceService.java | 3
src/main/java/com/moral/security/auth/JwtAuthenticationToken.java | 61 +
src/main/java/com/moral/security/model/UserContext.java | 58 +
src/main/java/com/moral/entity/MonitorPoint.java | 2
src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java | 68 ++
src/main/resources/mapper/DeviceMapper.xml | 14
src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java | 11
src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java | 31 +
src/main/java/com/moral/security/auth/login/LoginMode.java | 5
src/main/webapp/view/map.jsp | 10
src/main/java/com/moral/entity/Account.java | 11
src/main/resources/system/sysConfig.properties | 3
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java | 74 ++
src/main/java/com/moral/entity/Role.java | 8
src/main/java/com/moral/security/model/token/JwtToken.java | 5
src/main/java/com/moral/common/util/Crypto.java | 4
src/main/java/com/moral/security/RestAuthenticationEntryPoint.java | 26
src/main/java/com/moral/security/model/token/RawAccessJwtToken.java | 41 +
src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java | 18
src/main/java/com/moral/service/impl/DeviceServiceImpl.java | 14
src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java | 1
src/main/java/com/moral/security/config/PasswordEncoderConfig.java | 20
src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java | 82 ++
src/main/java/com/moral/security/model/token/RefreshToken.java | 65 ++
src/main/java/com/moral/security/config/JwtSettings.java | 59 +
src/main/java/com/moral/controller/MapController.java | 56 +
src/main/java/com/moral/mapper/DeviceMapper.java | 1
src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java | 26
src/main/java/com/moral/security/endpoint/ProfileEndpoint.java | 24
src/main/java/com/moral/service/AccountService.java | 2
src/main/java/com/moral/service/impl/AccountServiceImpl.java | 21
src/main/java/com/moral/security/common/WebUtil.java | 31 +
src/main/java/com/moral/security/config/WebSecurityConfig.java | 118 +++
src/main/java/com/moral/security/common/ErrorResponse.java | 52 +
src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java | 37 +
/dev/null | 89 --
src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java | 74 ++
src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java | 13
src/test/java/com/moral/JavaBeanToJsonOutPrint.java | 13
src/main/java/com/moral/security/auth/login/LoginRequest.java | 40 +
src/main/resources/mapper/MonitorPointMapper.xml | 25
src/main/java/com/moral/security/model/Scopes.java | 16
src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java | 17
src/main/java/com/moral/security/model/token/AccessJwtToken.java | 30
src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java | 64 ++
src/main/java/com/moral/security/exceptions/InvalidJwtToken.java | 12
src/main/resources/application.yml | 12
56 files changed, 1,641 insertions(+), 183 deletions(-)
diff --git a/src/main/java/com/moral/common/util/Crypto.java b/src/main/java/com/moral/common/util/Crypto.java
index 2a8be1a..14b2996 100644
--- a/src/main/java/com/moral/common/util/Crypto.java
+++ b/src/main/java/com/moral/common/util/Crypto.java
@@ -29,4 +29,8 @@
}
return newstr;
}
+ public static boolean checkpw(String plaintext, String hashed){
+ hashed = hashed == null?"":hashed;
+ return hashed.equals(md5(plaintext));
+ }
}
diff --git a/src/main/java/com/moral/config/MvcConfiguration.java b/src/main/java/com/moral/config/MvcConfiguration.java
index 7eff65c..7d63670 100644
--- a/src/main/java/com/moral/config/MvcConfiguration.java
+++ b/src/main/java/com/moral/config/MvcConfiguration.java
@@ -3,9 +3,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
-import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@@ -23,6 +21,4 @@
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
-
-
}
diff --git a/src/main/java/com/moral/controller/MapController.java b/src/main/java/com/moral/controller/MapController.java
index c32d4b5..88281a4 100644
--- a/src/main/java/com/moral/controller/MapController.java
+++ b/src/main/java/com/moral/controller/MapController.java
@@ -2,15 +2,17 @@
import com.alibaba.fastjson.JSONObject;
+import com.moral.common.bean.Constants;
import com.moral.common.bean.PageBean;
+import com.moral.common.bean.PageResult;
import com.moral.common.bean.ResultBean;
import com.moral.entity.Account;
+import com.moral.entity.Device;
import com.moral.entity.MapBounds;
import com.moral.entity.MonitorPoint;
-import com.moral.service.AccountService;
-import com.moral.service.AreaService;
-import com.moral.service.MonitorPointService;
-import com.moral.service.SensorService;
+import com.moral.service.*;
+import lombok.extern.log4j.Log4j;
+import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@@ -27,6 +29,9 @@
@Controller
@RequestMapping("map")
public class MapController {
+ public static Logger log = Logger.getLogger(MapController.class);
+ @Resource
+ DeviceService deviceService;
@Resource
AreaService areaService;
@Resource
@@ -35,22 +40,33 @@
SensorService sensorService;
@Resource
MonitorPointService monitorPointService;
+
@RequestMapping(value = "/main-page", method = RequestMethod.GET)
public String map(Model model,@RequestParam("areaCode")int code,@RequestParam("accountId")int accountId){
Account account = accountService.getAccountById(accountId);
String regionName = areaService.selectFullNameByCode(code);
- Object sensors = sensorService.queryAll();
- JSONObject params = new JSONObject();
- params.put("regionCode",code);
- params.put("regionName",regionName);
- params.put("accountId", accountId);
- params.put("orgId", account.getOrganizationId());
- params.put("sensors", sensors);
- String paramsJson = params.toJSONString();
- model.addAttribute("mapParams",paramsJson);
- return "map";
+ if(account!=null&®ionName!=null){
+ Object sensors = sensorService.queryAll();
+ JSONObject params = new JSONObject();
+ params.put("regionCode",code);
+ params.put("regionName",regionName);
+ params.put("accountId", accountId);
+ params.put("orgId", account.getOrganizationId());
+ params.put("sensors", sensors);
+ String paramsJson = params.toJSONString();
+ model.addAttribute("mapParams",paramsJson);
+ return "map";
+ } else {
+ StringBuilder msg = new StringBuilder();
+ msg.append(" param[0] areaCode:");
+ msg.append(code);
+ msg.append(" param[0] accountId:");
+ msg.append(accountId);
+ log.warn(msg);
+ return "401";
+ }
}
- @RequestMapping(value="/getmonitorpoints",method = RequestMethod.GET)
+ @RequestMapping(value="/get-monitorpoints",method = RequestMethod.GET)
@ResponseBody
public ResultBean getMonitorpointList(@RequestParam("orgId")String orgId,MapBounds mapBounds){
ResultBean< List<MonitorPoint>> resultBean = new ResultBean();
@@ -62,4 +78,14 @@
resultBean.setCode(ResultBean.SUCCESS);
return resultBean;
}
+ @RequestMapping(value = "get-devices-for-popup",method = RequestMethod.GET)
+ @ResponseBody
+ public PageResult getDevicesForPopup(
+ @RequestParam("orgId")Integer orgId,
+ String name,
+ Integer pageSize,
+ Integer pageNo
+ ){
+ return deviceService.query(orgId,name,pageSize,pageNo);
+ }
}
diff --git a/src/main/java/com/moral/entity/Account.java b/src/main/java/com/moral/entity/Account.java
index 02eb11e..1498df9 100644
--- a/src/main/java/com/moral/entity/Account.java
+++ b/src/main/java/com/moral/entity/Account.java
@@ -1,6 +1,8 @@
package com.moral.entity;
+import java.util.Arrays;
import java.util.Date;
+import java.util.List;
import javax.persistence.Id;
import javax.persistence.Transient;
@@ -71,7 +73,14 @@
private Date expireTime;
private String userName;
-
+ @Transient
+ private List<Role> Roles;
+ // TODO ������������
+ public List<Role> getRoles(){
+ Role role = new Role();
+ role.setName("temp");
+ return Arrays.asList(role);
+ }
@Transient
private Organization organization;
diff --git a/src/main/java/com/moral/entity/MonitorPoint.java b/src/main/java/com/moral/entity/MonitorPoint.java
index 3075b6a..5909997 100644
--- a/src/main/java/com/moral/entity/MonitorPoint.java
+++ b/src/main/java/com/moral/entity/MonitorPoint.java
@@ -96,6 +96,8 @@
*/
private String description;
@Transient
+ private Integer state;
+ @Transient
private AreaNames areaNames;
@Transient
private Organization organization;
diff --git a/src/main/java/com/moral/entity/Role.java b/src/main/java/com/moral/entity/Role.java
new file mode 100644
index 0000000..4ec205b
--- /dev/null
+++ b/src/main/java/com/moral/entity/Role.java
@@ -0,0 +1,8 @@
+package com.moral.entity;
+
+import lombok.Data;
+
+@Data
+public class Role {
+ private String name;
+}
diff --git a/src/main/java/com/moral/mapper/DeviceMapper.java b/src/main/java/com/moral/mapper/DeviceMapper.java
index 0fbc5c4..1eba557 100644
--- a/src/main/java/com/moral/mapper/DeviceMapper.java
+++ b/src/main/java/com/moral/mapper/DeviceMapper.java
@@ -14,4 +14,5 @@
List<Map<String, Object>> getDeviceStatesByAccount(Map<String, Object> parameters);
List<Device> selectWithRelationData(Example example);
List<Map<String, Object>> getSensorsByDevice(@Param("mac")String mac);
+ List<Device> selectByOrgIdAndDevName(@Param("orgId")Integer orgId,@Param("devName")String devName);
}
\ No newline at end of file
diff --git a/src/main/java/com/moral/mapper/MonitorPointMapper.java b/src/main/java/com/moral/mapper/MonitorPointMapper.java
index b0addba..f6244bc 100644
--- a/src/main/java/com/moral/mapper/MonitorPointMapper.java
+++ b/src/main/java/com/moral/mapper/MonitorPointMapper.java
@@ -11,5 +11,5 @@
List<MonitorPoint> selectWithAreaNameByExample(Example example);
List<MonitorPoint> getMonitorPointsByAreaName(Map<String, Object> parameters);
- List<MonitorPoint> selectWithStateByMap(Map<String, Object> params);
+ List<MonitorPoint> selectByMap(Map<String, Object> params);
}
\ No newline at end of file
diff --git a/src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java b/src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java
index 223d3a2..d853e1c 100644
--- a/src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java
+++ b/src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson.serializer.SerializerFeature;
import com.moral.common.json.BooleanValueFilter;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
diff --git a/src/main/java/com/moral/security/AuthorizationServerConfiguration.java b/src/main/java/com/moral/security/AuthorizationServerConfiguration.java
deleted file mode 100644
index c0b338f..0000000
--- a/src/main/java/com/moral/security/AuthorizationServerConfiguration.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.moral.security;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
-import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
-import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
-import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
-import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
-import org.springframework.security.oauth2.provider.token.TokenStore;
-
-@Configuration
-@EnableAuthorizationServer
-public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
-
- private static String REALM = "MY_OAUTH_REALM";
-
- @Autowired
- private UserDetailsService userDetailsService;
-
- @Autowired
- private TokenStore tokenStore;
-
- @Autowired
- private UserApprovalHandler userApprovalHandler;
-
- @Autowired
- @Qualifier("authenticationManagerBean")
- private AuthenticationManager authenticationManager;
-
- @Override
- public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
-
- clients.inMemory()
- .withClient("my-trusted-client")//���������ID
- .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
- .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
- .scopes("read", "write", "trust")//���������������������������
- .secret("secret")//������
- .accessTokenValiditySeconds(1200).//token������������1200���
- refreshTokenValiditySeconds(6000);//������token������������6000���
- }
-
- @Override
- public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
- endpoints.tokenStore(tokenStore)
- .userApprovalHandler(userApprovalHandler)
- .authenticationManager(authenticationManager)
- .userDetailsService(userDetailsService);
- }
-
- @Override
- public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
- oauthServer.realm(REALM + "/client");
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/moral/security/CustomCorsFilter.java b/src/main/java/com/moral/security/CustomCorsFilter.java
new file mode 100644
index 0000000..1de04cb
--- /dev/null
+++ b/src/main/java/com/moral/security/CustomCorsFilter.java
@@ -0,0 +1,33 @@
+package com.moral.security;
+
+import java.util.Arrays;
+
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * CustomCorsFilter
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public class CustomCorsFilter extends CorsFilter {
+
+ public CustomCorsFilter() {
+ super(configurationSource());
+ }
+
+ private static UrlBasedCorsConfigurationSource configurationSource() {
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ config.addAllowedOrigin("*");
+ config.addAllowedHeader("*");
+ config.setMaxAge(36000L);
+ config.setAllowedMethods(Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"));
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ return source;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/moral/security/ResourceServerConfiguration.java b/src/main/java/com/moral/security/ResourceServerConfiguration.java
deleted file mode 100644
index edde722..0000000
--- a/src/main/java/com/moral/security/ResourceServerConfiguration.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.moral.security;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
-import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
-import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
-import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
-
-@Configuration
-@EnableResourceServer
-public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
-
- private static final String RESOURCE_ID = "my_rest_api";
-
- @Override
- public void configure(ResourceServerSecurityConfigurer resources) {
- resources.resourceId(RESOURCE_ID).stateless(false);
- }
-
- @Override
- public void configure(HttpSecurity http) throws Exception {
- http.anonymous().disable();
- http.requestMatchers()
- .antMatchers("/test/**")
- .and()
- .authorizeRequests()
- .antMatchers("/test/**").permitAll()
- .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
-
- /*http.requestMatchers()
- .antMatchers("/screen/**")
- .and()
- .authorizeRequests()
- .antMatchers("/screen/**").permitAll()
- .and()
- .exceptionHandling()
- .accessDeniedHandler(new OAuth2AccessDeniedHandler());*/
-
- /*http.requestMatchers()
- .antMatchers("/mobile/**")
- .and()
- .authorizeRequests()
- .antMatchers("/mobile/**").permitAll()
- .and()
- .exceptionHandling()
- .accessDeniedHandler(new OAuth2AccessDeniedHandler());*/
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/moral/security/RestAuthenticationEntryPoint.java b/src/main/java/com/moral/security/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000..b9ceb05
--- /dev/null
+++ b/src/main/java/com/moral/security/RestAuthenticationEntryPoint.java
@@ -0,0 +1,26 @@
+package com.moral.security;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 4, 2016
+ */
+@Component
+public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex)
+ throws IOException, ServletException {
+ response.sendError(HttpStatus.UNAUTHORIZED.value(), "Unauthorized");
+ }
+}
diff --git a/src/main/java/com/moral/security/WebMvcConfiguration.java b/src/main/java/com/moral/security/WebMvcConfiguration.java
deleted file mode 100644
index c81dd9f..0000000
--- a/src/main/java/com/moral/security/WebMvcConfiguration.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.moral.security;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-
-@Configuration
-@EnableWebMvc
-public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**").allowedOrigins("*")
- .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS")
- .allowCredentials(false).maxAge(3600);
-
-// registry.addMapping("/api/**")
-// .allowedOrigins("http://192.168.1.97")
-// .allowedMethods("GET", "POST")
-// .allowCredentials(false).maxAge(3600);
- }
-}
diff --git a/src/main/java/com/moral/security/WebSecurityConfiguration.java b/src/main/java/com/moral/security/WebSecurityConfiguration.java
deleted file mode 100644
index d54621f..0000000
--- a/src/main/java/com/moral/security/WebSecurityConfiguration.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.moral.security;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.security.SecurityProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.crypto.password.NoOpPasswordEncoder;
-import org.springframework.security.oauth2.provider.ClientDetailsService;
-import org.springframework.security.oauth2.provider.approval.ApprovalStore;
-import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
-import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
-import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
-import org.springframework.security.oauth2.provider.token.TokenStore;
-import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
-import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
-
-@Configuration
-@EnableWebSecurity
-@EnableGlobalMethodSecurity(prePostEnabled = true)
-@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
-public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
-
- @Autowired
- private ClientDetailsService clientDetailsService;
-
- @Autowired
- private RedisConnectionFactory redisConnection;
-
- @Autowired
- private UserDetailsService userDetailsService;
-
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.inMemoryAuthentication()
- .withUser("bill").password("abc123").roles("ADMIN").and()
- .withUser("bob").password("abc123").roles("USER");
-
- auth.userDetailsService(userDetailsService).passwordEncoder(NoOpPasswordEncoder.getInstance());
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.csrf().disable(); //TODO ������������CSRF
- http.anonymous().disable()
- .authorizeRequests()
- .antMatchers("/oauth/token").permitAll();
- }
-
- @Override
- @Bean
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
- }
-
-
- @Bean
- public TokenStore tokenStore() {
- return new InMemoryTokenStore();
- //return new RedisTokenStore(redisConnection);
- }
-
- @Bean
- @Autowired
- public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
- TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
- handler.setTokenStore(tokenStore);
- handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
- handler.setClientDetailsService(clientDetailsService);
- return handler;
- }
-
- @Bean
- @Autowired
- public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
- TokenApprovalStore store = new TokenApprovalStore();
- store.setTokenStore(tokenStore);
- return store;
- }
-}
diff --git a/src/main/java/com/moral/security/auth/JwtAuthenticationToken.java b/src/main/java/com/moral/security/auth/JwtAuthenticationToken.java
new file mode 100644
index 0000000..989f525
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/JwtAuthenticationToken.java
@@ -0,0 +1,61 @@
+package com.moral.security.auth;
+
+import com.moral.security.model.UserContext;
+import com.moral.security.model.token.RawAccessJwtToken;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+
+/**
+ * An {@link org.springframework.security.core.Authentication} implementation
+ * that is designed for simple presentation of JwtToken.
+ *
+ * @author vladimir.stankovic
+ *
+ * May 23, 2016
+ */
+public class JwtAuthenticationToken extends AbstractAuthenticationToken {
+ private static final long serialVersionUID = 2877954820905567501L;
+
+ private RawAccessJwtToken rawAccessToken;
+ private UserContext userContext;
+
+ public JwtAuthenticationToken(RawAccessJwtToken unsafeToken) {
+ super(null);
+ this.rawAccessToken = unsafeToken;
+ this.setAuthenticated(false);
+ }
+
+ public JwtAuthenticationToken(UserContext userContext, Collection<? extends GrantedAuthority> authorities) {
+ super(authorities);
+ this.eraseCredentials();
+ this.userContext = userContext;
+ super.setAuthenticated(true);
+ }
+
+ @Override
+ public void setAuthenticated(boolean authenticated) {
+ if (authenticated) {
+ throw new IllegalArgumentException(
+ "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
+ }
+ super.setAuthenticated(false);
+ }
+
+ @Override
+ public Object getCredentials() {
+ return rawAccessToken;
+ }
+
+ @Override
+ public UserContext getPrincipal() {
+ return this.userContext;
+ }
+
+ @Override
+ public void eraseCredentials() {
+ super.eraseCredentials();
+ this.rawAccessToken = null;
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java b/src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java
new file mode 100644
index 0000000..3afe42a
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java
@@ -0,0 +1,68 @@
+package com.moral.security.auth.jwt;
+
+import com.moral.security.auth.JwtAuthenticationToken;
+import com.moral.security.auth.login.LoginMode;
+import com.moral.security.config.JwtSettings;
+import com.moral.security.model.UserContext;
+import com.moral.security.model.token.JwtToken;
+import com.moral.security.model.token.RawAccessJwtToken;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * An {@link AuthenticationProvider} implementation that will use provided
+ * instance of {@link JwtToken} to perform authentication.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 5, 2016
+ */
+@Component
+@SuppressWarnings("unchecked")
+public class JwtAuthenticationProvider implements AuthenticationProvider {
+ private final JwtSettings jwtSettings;
+
+ @Autowired
+ public JwtAuthenticationProvider(JwtSettings jwtSettings) {
+ this.jwtSettings = jwtSettings;
+ }
+
+ /**
+ * ���������������������������������������������������������
+ * @param authentication
+ * @return
+ * @throws AuthenticationException
+ */
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+ RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
+
+ Jws<Claims> jwsClaims = rawAccessToken.parseClaims(jwtSettings.getTokenSigningKey());
+ String subject = jwsClaims.getBody().getSubject();
+ Integer orgId = Integer.valueOf(jwsClaims.getBody().get("oid").toString());
+ LoginMode mode = LoginMode.valueOf(jwsClaims.getBody().get("mode").toString());
+ List<String> scopes = jwsClaims.getBody().get("scopes", List.class);
+ List<GrantedAuthority> authorities = scopes.stream()
+ .map(SimpleGrantedAuthority::new)
+ .collect(Collectors.toList());
+
+ UserContext context = UserContext.create(subject,mode,orgId,authorities);
+
+ return new JwtAuthenticationToken(context, context.getAuthorities());
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java b/src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java
new file mode 100644
index 0000000..4fb6f49
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java
@@ -0,0 +1,64 @@
+package com.moral.security.auth.jwt;
+
+import com.moral.security.auth.JwtAuthenticationToken;
+import com.moral.security.auth.jwt.extractor.TokenExtractor;
+import com.moral.security.config.WebSecurityConfig;
+import com.moral.security.model.token.RawAccessJwtToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Performs validation of provided JWT Token.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 5, 2016
+ */
+public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
+ private final AuthenticationFailureHandler failureHandler;
+ private final TokenExtractor tokenExtractor;
+
+ @Autowired
+ public JwtTokenAuthenticationProcessingFilter(AuthenticationFailureHandler failureHandler,
+ TokenExtractor tokenExtractor, RequestMatcher matcher) {
+ super(matcher);
+ this.failureHandler = failureHandler;
+ this.tokenExtractor = tokenExtractor;
+ }
+
+ @Override
+ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
+ throws AuthenticationException, IOException, ServletException {
+ String tokenPayload = request.getHeader(WebSecurityConfig.AUTHENTICATION_HEADER_NAME);
+ RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
+ return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
+ }
+
+ @Override
+ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
+ Authentication authResult) throws IOException, ServletException {
+ SecurityContext context = SecurityContextHolder.createEmptyContext();
+ context.setAuthentication(authResult);
+ SecurityContextHolder.setContext(context);
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException failed) throws IOException, ServletException {
+ SecurityContextHolder.clearContext();
+ failureHandler.onAuthenticationFailure(request, response, failed);
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java b/src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java
new file mode 100644
index 0000000..7c747d8
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java
@@ -0,0 +1,37 @@
+package com.moral.security.auth.jwt;
+
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.OrRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.util.Assert;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * SkipPathRequestMatcher
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 19, 2016
+ */
+public class SkipPathRequestMatcher implements RequestMatcher {
+ private OrRequestMatcher matchers;
+ private RequestMatcher processingMatcher;
+
+ public SkipPathRequestMatcher(List<String> pathsToSkip, String processingPath) {
+ Assert.notNull(pathsToSkip);
+ List<RequestMatcher> m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList());
+ matchers = new OrRequestMatcher(m);
+ processingMatcher = new AntPathRequestMatcher(processingPath);
+ }
+
+ @Override
+ public boolean matches(HttpServletRequest request) {
+ if (matchers.matches(request)) {
+ return false;
+ }
+ return processingMatcher.matches(request) ? true : false;
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java b/src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java
new file mode 100644
index 0000000..bf2fc27
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java
@@ -0,0 +1,31 @@
+package com.moral.security.auth.jwt.extractor;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.stereotype.Component;
+
+/**
+ * An implementation of {@link TokenExtractor} extracts token from
+ * Authorization: Bearer scheme.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 5, 2016
+ */
+@Component
+public class JwtHeaderTokenExtractor implements TokenExtractor {
+ public static String HEADER_PREFIX = "Bearer ";
+
+ @Override
+ public String extract(String header) {
+ if (StringUtils.isBlank(header)) {
+ throw new AuthenticationServiceException("Authorization header cannot be blank!");
+ }
+
+ if (header.length() < HEADER_PREFIX.length()) {
+ throw new AuthenticationServiceException("Invalid authorization header size.");
+ }
+
+ return header.substring(HEADER_PREFIX.length(), header.length());
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java b/src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java
new file mode 100644
index 0000000..79cf7d4
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java
@@ -0,0 +1,13 @@
+package com.moral.security.auth.jwt.extractor;
+
+/**
+ * Implementations of this interface should always return raw base-64 encoded
+ * representation of JWT Token.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 5, 2016
+ */
+public interface TokenExtractor {
+ public String extract(String payload);
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java b/src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java
new file mode 100644
index 0000000..d2ed3c2
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java
@@ -0,0 +1,18 @@
+package com.moral.security.auth.jwt.verifier;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * BloomFilterTokenVerifier
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 17, 2016
+ */
+@Component
+public class BloomFilterTokenVerifier implements TokenVerifier {
+ @Override
+ public boolean verify(String jti) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java b/src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java
new file mode 100644
index 0000000..0e6d014
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java
@@ -0,0 +1,11 @@
+package com.moral.security.auth.jwt.verifier;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 17, 2016
+ */
+public interface TokenVerifier {
+ public boolean verify(String jti);
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java b/src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java
new file mode 100644
index 0000000..307d880
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java
@@ -0,0 +1,74 @@
+package com.moral.security.auth.login;
+
+import com.moral.entity.Account;
+import com.moral.security.model.UserContext;
+import com.moral.service.AccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author vladimir.stankovic
+ * <p>
+ * Aug 3, 2016
+ */
+@Component
+public class LoginAuthenticationProvider implements AuthenticationProvider {
+ private final BCryptPasswordEncoder encoder;
+ private final AccountService accountService;
+
+ @Autowired
+ public LoginAuthenticationProvider(final AccountService accountService, final BCryptPasswordEncoder encoder) {
+ this.accountService = accountService;
+ this.encoder = encoder;
+ }
+
+ /**
+ * ������������������������
+ *
+ * @param authentication
+ * @return
+ * @throws AuthenticationException
+ */
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+ Assert.notNull(authentication, "No authentication data provided");
+
+ String accountName = (String) authentication.getPrincipal();
+ String password = (String) authentication.getCredentials();
+ LoginMode mode = (LoginMode) authentication.getDetails();
+ Account account = accountService.queryAccountByName(accountName).orElseThrow(() -> new UsernameNotFoundException("User not found: " + accountName));
+ if (!encoder.matches(password, account.getPassword())) {
+ throw new BadCredentialsException("Authentication Failed. Username or Password not valid.");
+ }
+
+ if (account.getRoles() == null) {
+ throw new InsufficientAuthenticationException("User has no roles assigned");
+ }
+ List<GrantedAuthority> authorities = account.getRoles().stream()
+ .map(authority -> new SimpleGrantedAuthority(authority.getName()))
+ .collect(Collectors.toList());
+
+ UserContext userContext = UserContext.create(account.getAccountName(),mode,account.getOrganizationId(),authorities);
+
+ return new UsernamePasswordAuthenticationToken(userContext, null, userContext.getAuthorities());
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java b/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java
new file mode 100644
index 0000000..60c94ae
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java
@@ -0,0 +1,53 @@
+package com.moral.security.auth.login;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.moral.security.common.ErrorCode;
+import com.moral.security.common.ErrorResponse;
+import com.moral.security.exceptions.AuthMethodNotSupportedException;
+import com.moral.security.exceptions.JwtExpiredTokenException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+@Component
+public class LoginAwareAuthenticationFailureHandler implements AuthenticationFailureHandler {
+ private final ObjectMapper mapper;
+
+ @Autowired
+ public LoginAwareAuthenticationFailureHandler(ObjectMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException e) throws IOException, ServletException {
+
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+
+ if (e instanceof BadCredentialsException) {
+ mapper.writeValue(response.getWriter(), ErrorResponse.of("Invalid username or password", ErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
+ } else if (e instanceof JwtExpiredTokenException) {
+ mapper.writeValue(response.getWriter(), ErrorResponse.of("Token has expired", ErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED));
+ } else if (e instanceof AuthMethodNotSupportedException) {
+ mapper.writeValue(response.getWriter(), ErrorResponse.of(e.getMessage(), ErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
+ }
+
+ mapper.writeValue(response.getWriter(), ErrorResponse.of("Authentication failed", ErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java b/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java
new file mode 100644
index 0000000..02c6d29
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java
@@ -0,0 +1,74 @@
+package com.moral.security.auth.login;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.moral.security.model.UserContext;
+import com.moral.security.model.token.JwtToken;
+import com.moral.security.model.token.JwtTokenFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.WebAttributes;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * AjaxAwareAuthenticationSuccessHandler
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+@Component
+public class LoginAwareAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
+ private final ObjectMapper mapper;
+ private final JwtTokenFactory tokenFactory;
+
+ @Autowired
+ public LoginAwareAuthenticationSuccessHandler(final ObjectMapper mapper, final JwtTokenFactory tokenFactory) {
+ this.mapper = mapper;
+ this.tokenFactory = tokenFactory;
+ }
+
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
+ Authentication authentication) throws IOException, ServletException {
+ UserContext userContext = (UserContext) authentication.getPrincipal();
+
+ JwtToken accessToken = tokenFactory.createAccessJwtToken(userContext);
+ JwtToken refreshToken = tokenFactory.createRefreshToken(userContext);
+
+ Map<String, String> tokenMap = new HashMap<String, String>();
+ tokenMap.put("token", accessToken.getToken());
+ tokenMap.put("refreshToken", refreshToken.getToken());
+
+ response.setStatus(HttpStatus.OK.value());
+ response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+ mapper.writeValue(response.getWriter(), tokenMap);
+
+ clearAuthenticationAttributes(request);
+ }
+
+ /**
+ * Removes temporary authentication-related data which may have been stored
+ * in the session during the authentication process..
+ *
+ */
+ protected final void clearAuthenticationAttributes(HttpServletRequest request) {
+ HttpSession session = request.getSession(false);
+
+ if (session == null) {
+ return;
+ }
+
+ session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginMode.java b/src/main/java/com/moral/security/auth/login/LoginMode.java
new file mode 100644
index 0000000..4681349
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginMode.java
@@ -0,0 +1,5 @@
+package com.moral.security.auth.login;
+
+public enum LoginMode {
+ Web,Screen,Andriod,Apple
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java b/src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java
new file mode 100644
index 0000000..6f411ea
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java
@@ -0,0 +1,84 @@
+package com.moral.security.auth.login;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.moral.security.common.WebUtil;
+import com.moral.security.exceptions.AuthMethodNotSupportedException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * AjaxLoginProcessingFilter
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public class LoginProcessingFilter extends AbstractAuthenticationProcessingFilter {
+ private static Logger logger = LoggerFactory.getLogger(LoginProcessingFilter.class);
+
+ private final AuthenticationSuccessHandler successHandler;
+ private final AuthenticationFailureHandler failureHandler;
+
+ private final ObjectMapper objectMapper;
+
+ public LoginProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler,
+ AuthenticationFailureHandler failureHandler, ObjectMapper mapper) {
+ super(defaultProcessUrl);
+ this.successHandler = successHandler;
+ this.failureHandler = failureHandler;
+ this.objectMapper = mapper;
+ }
+
+ @Override
+ public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
+ throws AuthenticationException, IOException, ServletException {
+ if (!HttpMethod.POST.name().equals(request.getMethod())) {
+ if(logger.isDebugEnabled()) {
+ logger.debug("Authentication method not supported. Request method: " + request.getMethod());
+ }
+ throw new AuthMethodNotSupportedException("Authentication method not supported");
+ }
+
+ LoginRequest loginRequest = objectMapper.readValue(request.getReader(), LoginRequest.class);
+
+ if (StringUtils.isBlank(loginRequest.getUsername())
+ || StringUtils.isBlank(loginRequest.getPassword())
+ || loginRequest.getMode() == null) {
+ throw new AuthenticationServiceException("Username or Password not provided");
+ }
+
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
+ // ������������������������������������������������
+ token.setDetails(loginRequest.getMode());
+ return this.getAuthenticationManager().authenticate(token);
+ }
+
+ @Override
+ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
+ Authentication authResult) throws IOException, ServletException {
+ successHandler.onAuthenticationSuccess(request, response, authResult);
+ }
+
+ @Override
+ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException failed) throws IOException, ServletException {
+ SecurityContextHolder.clearContext();
+ failureHandler.onAuthenticationFailure(request, response, failed);
+ }
+}
diff --git a/src/main/java/com/moral/security/auth/login/LoginRequest.java b/src/main/java/com/moral/security/auth/login/LoginRequest.java
new file mode 100644
index 0000000..be34bf8
--- /dev/null
+++ b/src/main/java/com/moral/security/auth/login/LoginRequest.java
@@ -0,0 +1,40 @@
+package com.moral.security.auth.login;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Model intended to be used for AJAX based authentication.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+
+public class LoginRequest {
+ private String username;
+ private String password;
+
+ public LoginMode getMode() {
+ return mode;
+ }
+
+ private LoginMode mode;
+
+ @JsonCreator
+ public LoginRequest(@JsonProperty("username") String username,
+ @JsonProperty("password") String password,
+ @JsonProperty("mode") LoginMode mode) {
+ this.username = username;
+ this.password = password;
+ this.mode = mode;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/main/java/com/moral/security/common/ErrorCode.java b/src/main/java/com/moral/security/common/ErrorCode.java
new file mode 100644
index 0000000..db6750d
--- /dev/null
+++ b/src/main/java/com/moral/security/common/ErrorCode.java
@@ -0,0 +1,27 @@
+package com.moral.security.common;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Enumeration of REST Error types.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public enum ErrorCode {
+ GLOBAL(2),
+
+ AUTHENTICATION(10), JWT_TOKEN_EXPIRED(11);
+
+ private int errorCode;
+
+ private ErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ @JsonValue
+ public int getErrorCode() {
+ return errorCode;
+ }
+}
diff --git a/src/main/java/com/moral/security/common/ErrorResponse.java b/src/main/java/com/moral/security/common/ErrorResponse.java
new file mode 100644
index 0000000..ec30c90
--- /dev/null
+++ b/src/main/java/com/moral/security/common/ErrorResponse.java
@@ -0,0 +1,52 @@
+package com.moral.security.common;
+
+import org.springframework.http.HttpStatus;
+
+import java.util.Date;
+
+/**
+ * Error model for interacting with client.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public class ErrorResponse {
+ // HTTP Response Status Code
+ private final HttpStatus status;
+
+ // General Error message
+ private final String message;
+
+ // Error code
+ private final ErrorCode errorCode;
+
+ private final Date timestamp;
+
+ protected ErrorResponse(final String message, final ErrorCode errorCode, HttpStatus status) {
+ this.message = message;
+ this.errorCode = errorCode;
+ this.status = status;
+ this.timestamp = new Date();
+ }
+
+ public static ErrorResponse of(final String message, final ErrorCode errorCode, HttpStatus status) {
+ return new ErrorResponse(message, errorCode, status);
+ }
+
+ public Integer getStatus() {
+ return status.value();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public ErrorCode getErrorCode() {
+ return errorCode;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+}
diff --git a/src/main/java/com/moral/security/common/WebUtil.java b/src/main/java/com/moral/security/common/WebUtil.java
new file mode 100644
index 0000000..2a1e822
--- /dev/null
+++ b/src/main/java/com/moral/security/common/WebUtil.java
@@ -0,0 +1,31 @@
+package com.moral.security.common;
+
+import org.springframework.security.web.savedrequest.SavedRequest;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public class WebUtil {
+ private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
+ private static final String X_REQUESTED_WITH = "X-Requested-With";
+
+ private static final String CONTENT_TYPE = "Content-type";
+ private static final String CONTENT_TYPE_JSON = "application/json";
+
+ public static boolean isAjax(HttpServletRequest request) {
+ return XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH));
+ }
+
+ public static boolean isAjax(SavedRequest request) {
+ return request.getHeaderValues(X_REQUESTED_WITH).contains(XML_HTTP_REQUEST);
+ }
+
+ public static boolean isContentTypeJson(SavedRequest request) {
+ return request.getHeaderValues(CONTENT_TYPE).contains(CONTENT_TYPE_JSON);
+ }
+}
diff --git a/src/main/java/com/moral/security/config/JwtSettings.java b/src/main/java/com/moral/security/config/JwtSettings.java
new file mode 100644
index 0000000..fc96aac
--- /dev/null
+++ b/src/main/java/com/moral/security/config/JwtSettings.java
@@ -0,0 +1,59 @@
+package com.moral.security.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "moral.security.jwt")
+public class JwtSettings {
+ /**
+ * {@link JwtToken} will expire after this time.
+ */
+ private Integer tokenExpirationTime;
+
+ /**
+ * Token issuer.
+ */
+ private String tokenIssuer;
+
+ /**
+ * Key is used to sign {@link JwtToken}.
+ */
+ private String tokenSigningKey;
+
+ /**
+ * {@link JwtToken} can be refreshed during this timeframe.
+ */
+ private Integer refreshTokenExpTime;
+
+ public Integer getRefreshTokenExpTime() {
+ return refreshTokenExpTime;
+ }
+
+ public void setRefreshTokenExpTime(Integer refreshTokenExpTime) {
+ this.refreshTokenExpTime = refreshTokenExpTime;
+ }
+
+ public Integer getTokenExpirationTime() {
+ return tokenExpirationTime;
+ }
+
+ public void setTokenExpirationTime(Integer tokenExpirationTime) {
+ this.tokenExpirationTime = tokenExpirationTime;
+ }
+
+ public String getTokenIssuer() {
+ return tokenIssuer;
+ }
+ public void setTokenIssuer(String tokenIssuer) {
+ this.tokenIssuer = tokenIssuer;
+ }
+
+ public String getTokenSigningKey() {
+ return tokenSigningKey;
+ }
+
+ public void setTokenSigningKey(String tokenSigningKey) {
+ this.tokenSigningKey = tokenSigningKey;
+ }
+}
diff --git a/src/main/java/com/moral/security/config/PasswordEncoderConfig.java b/src/main/java/com/moral/security/config/PasswordEncoderConfig.java
new file mode 100644
index 0000000..12de433
--- /dev/null
+++ b/src/main/java/com/moral/security/config/PasswordEncoderConfig.java
@@ -0,0 +1,20 @@
+package com.moral.security.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * PasswordEncoderConfig
+ *
+ * @author vladimir.stankovic
+ *
+ * Dec 27, 2016
+ */
+@Configuration
+public class PasswordEncoderConfig {
+ @Bean
+ protected BCryptPasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/src/main/java/com/moral/security/config/WebSecurityConfig.java b/src/main/java/com/moral/security/config/WebSecurityConfig.java
new file mode 100644
index 0000000..d6b75e9
--- /dev/null
+++ b/src/main/java/com/moral/security/config/WebSecurityConfig.java
@@ -0,0 +1,118 @@
+package com.moral.security.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.moral.security.CustomCorsFilter;
+import com.moral.security.RestAuthenticationEntryPoint;
+import com.moral.security.auth.login.LoginAuthenticationProvider;
+import com.moral.security.auth.login.LoginProcessingFilter;
+import com.moral.security.auth.jwt.JwtAuthenticationProvider;
+import com.moral.security.auth.jwt.JwtTokenAuthenticationProcessingFilter;
+import com.moral.security.auth.jwt.SkipPathRequestMatcher;
+import com.moral.security.auth.jwt.extractor.TokenExtractor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * WebSecurityConfig
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+ public static final String AUTHENTICATION_HEADER_NAME = "X-Authorization";
+ public static final String AUTHENTICATION_URL = "/auth/login";
+ public static final String REFRESH_TOKEN_URL = "/auth/token";
+ public static final String API_ROOT_URL = "/*/**";
+
+ @Autowired
+ private RestAuthenticationEntryPoint authenticationEntryPoint;
+ @Autowired
+ private AuthenticationSuccessHandler successHandler;
+ @Autowired
+ private AuthenticationFailureHandler failureHandler;
+ @Autowired
+ private LoginAuthenticationProvider ajaxAuthenticationProvider;
+ @Autowired
+ private JwtAuthenticationProvider jwtAuthenticationProvider;
+
+ @Autowired
+ private TokenExtractor tokenExtractor;
+
+ @Autowired
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ protected LoginProcessingFilter buildLoginProcessingFilter(String loginEntryPoint) throws Exception {
+ LoginProcessingFilter filter = new LoginProcessingFilter(loginEntryPoint, successHandler, failureHandler, objectMapper);
+ filter.setAuthenticationManager(this.authenticationManager);
+ return filter;
+ }
+
+ protected JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter(List<String> pathsToSkip, String pattern) throws Exception {
+ SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(pathsToSkip, pattern);
+ JwtTokenAuthenticationProcessingFilter filter
+ = new JwtTokenAuthenticationProcessingFilter(failureHandler, tokenExtractor, matcher);
+ filter.setAuthenticationManager(this.authenticationManager);
+ return filter;
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) {
+ auth.authenticationProvider(ajaxAuthenticationProvider);
+ auth.authenticationProvider(jwtAuthenticationProvider);
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ List<String> permitAllEndpointList = Arrays.asList(
+ AUTHENTICATION_URL,
+ REFRESH_TOKEN_URL
+ );
+
+ http
+ .csrf().disable() // We don't need CSRF for JWT based authentication
+ .exceptionHandling()
+ .authenticationEntryPoint(this.authenticationEntryPoint)
+
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+
+ .and()
+ .authorizeRequests()
+ .antMatchers(permitAllEndpointList.toArray(new String[permitAllEndpointList.size()]))
+ .permitAll()
+ .and()
+ .authorizeRequests()
+ .antMatchers(API_ROOT_URL).authenticated() // Protected API End-points
+ .and()
+ .addFilterBefore(new CustomCorsFilter(), UsernamePasswordAuthenticationFilter.class)
+ .addFilterBefore(buildLoginProcessingFilter(AUTHENTICATION_URL), UsernamePasswordAuthenticationFilter.class)
+ .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(permitAllEndpointList,
+ API_ROOT_URL), UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/src/main/java/com/moral/security/endpoint/ProfileEndpoint.java b/src/main/java/com/moral/security/endpoint/ProfileEndpoint.java
new file mode 100644
index 0000000..9349580
--- /dev/null
+++ b/src/main/java/com/moral/security/endpoint/ProfileEndpoint.java
@@ -0,0 +1,24 @@
+package com.moral.security.endpoint;
+
+import com.moral.security.auth.JwtAuthenticationToken;
+import com.moral.security.model.UserContext;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * End-point for retrieving logged-in user details.
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 4, 2016
+ */
+@RestController
+public class ProfileEndpoint {
+ @RequestMapping(value="/user-context", method=RequestMethod.GET)
+ public @ResponseBody
+ UserContext get(JwtAuthenticationToken token) {
+ return token.getPrincipal();
+ }
+}
diff --git a/src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java b/src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java
new file mode 100644
index 0000000..f965e0f
--- /dev/null
+++ b/src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java
@@ -0,0 +1,82 @@
+package com.moral.security.endpoint;
+
+import com.moral.entity.Account;
+import com.moral.security.auth.JwtAuthenticationToken;
+import com.moral.security.auth.login.LoginMode;
+import com.moral.security.model.token.JwtTokenFactory;
+import com.moral.security.auth.jwt.extractor.TokenExtractor;
+import com.moral.security.auth.jwt.verifier.TokenVerifier;
+import com.moral.security.config.JwtSettings;
+import com.moral.security.config.WebSecurityConfig;
+import com.moral.security.exceptions.InvalidJwtToken;
+import com.moral.security.model.UserContext;
+import com.moral.security.model.token.JwtToken;
+import com.moral.security.model.token.RawAccessJwtToken;
+import com.moral.security.model.token.RefreshToken;
+import com.moral.service.AccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * RefreshTokenEndpoint
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 17, 2016
+ */
+@RestController
+public class RefreshTokenEndpoint {
+ @Autowired
+ private JwtTokenFactory tokenFactory;
+ @Autowired
+ private JwtSettings jwtSettings;
+ @Autowired
+ private AccountService accountService;
+ @Autowired
+ private TokenVerifier tokenVerifier;
+ @Autowired
+ @Qualifier("jwtHeaderTokenExtractor") private TokenExtractor tokenExtractor;
+
+ @RequestMapping(value="/auth/token", method= RequestMethod.GET, produces={ MediaType.APPLICATION_JSON_VALUE })
+ public @ResponseBody
+ JwtToken refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
+ String tokenPayload = tokenExtractor.extract(request.getHeader(WebSecurityConfig.AUTHENTICATION_HEADER_NAME));
+
+ RawAccessJwtToken rawToken = new RawAccessJwtToken(tokenPayload);
+ RefreshToken refreshToken = RefreshToken.create(rawToken, jwtSettings.getTokenSigningKey()).orElseThrow(() -> new InvalidJwtToken());
+
+ String jti = refreshToken.getJti();
+ if (!tokenVerifier.verify(jti)) {
+ throw new InvalidJwtToken();
+ }
+ String subject = refreshToken.getSubject();
+ // ���refresh token��� ������������������
+ LoginMode mode = LoginMode.valueOf(refreshToken.getClaims().getBody().get("mode").toString());
+ Account account = accountService.queryAccountByName(subject).orElseThrow(() -> new UsernameNotFoundException("User not found: " + subject));
+
+ if (account.getRoles() == null) throw new InsufficientAuthenticationException("User has no roles assigned");
+ List<GrantedAuthority> authorities = account.getRoles().stream()
+ .map(authority -> new SimpleGrantedAuthority(authority.getName()))
+ .collect(Collectors.toList());
+
+ UserContext userContext = UserContext.create(account.getAccountName(),mode,account.getOrganizationId(),authorities);
+
+ return tokenFactory.createAccessJwtToken(userContext);
+ }
+}
diff --git a/src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java b/src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java
new file mode 100644
index 0000000..9b6db5c
--- /dev/null
+++ b/src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java
@@ -0,0 +1,17 @@
+package com.moral.security.exceptions;
+
+import org.springframework.security.authentication.AuthenticationServiceException;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 4, 2016
+ */
+public class AuthMethodNotSupportedException extends AuthenticationServiceException {
+ private static final long serialVersionUID = 3705043083010304496L;
+
+ public AuthMethodNotSupportedException(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/main/java/com/moral/security/exceptions/InvalidJwtToken.java b/src/main/java/com/moral/security/exceptions/InvalidJwtToken.java
new file mode 100644
index 0000000..d4c64ec
--- /dev/null
+++ b/src/main/java/com/moral/security/exceptions/InvalidJwtToken.java
@@ -0,0 +1,12 @@
+package com.moral.security.exceptions;
+
+/**
+ * JwtTokenNotValid
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 17, 2016
+ */
+public class InvalidJwtToken extends RuntimeException {
+ private static final long serialVersionUID = -294671188037098603L;
+}
diff --git a/src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java b/src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java
new file mode 100644
index 0000000..0259570
--- /dev/null
+++ b/src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java
@@ -0,0 +1,29 @@
+package com.moral.security.exceptions;
+
+import com.moral.security.model.token.JwtToken;
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 3, 2016
+ */
+public class JwtExpiredTokenException extends AuthenticationException {
+ private static final long serialVersionUID = -5959543783324224864L;
+
+ private JwtToken token;
+
+ public JwtExpiredTokenException(String msg) {
+ super(msg);
+ }
+
+ public JwtExpiredTokenException(JwtToken token, String msg, Throwable t) {
+ super(msg, t);
+ this.token = token;
+ }
+
+ public String token() {
+ return this.token.getToken();
+ }
+}
diff --git a/src/main/java/com/moral/security/model/Scopes.java b/src/main/java/com/moral/security/model/Scopes.java
new file mode 100644
index 0000000..b6dbc24
--- /dev/null
+++ b/src/main/java/com/moral/security/model/Scopes.java
@@ -0,0 +1,16 @@
+package com.moral.security.model;
+
+/**
+ * Scopes
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 18, 2016
+ */
+public enum Scopes {
+ REFRESH_TOKEN;
+
+ public String authority() {
+ return "ROLE_" + this.name();
+ }
+}
diff --git a/src/main/java/com/moral/security/model/UserContext.java b/src/main/java/com/moral/security/model/UserContext.java
new file mode 100644
index 0000000..cc9e8b1
--- /dev/null
+++ b/src/main/java/com/moral/security/model/UserContext.java
@@ -0,0 +1,58 @@
+package com.moral.security.model;
+
+import com.moral.security.auth.login.LoginMode;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.List;
+
+/**
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 4, 2016
+ */
+public class UserContext {
+ private final String username;
+
+ public LoginMode getMode() {
+ return mode;
+ }
+
+ private final LoginMode mode;
+
+ public Integer getOrganizationId() {
+ return organizationId;
+ }
+
+ private final Integer organizationId;
+ private final List<GrantedAuthority> authorities;
+
+ private UserContext(String username, LoginMode mode, Integer organizationId, List<GrantedAuthority> authorities) {
+ this.username = username;
+ this.mode = mode;
+ this.organizationId = organizationId;
+ this.authorities = authorities;
+ }
+
+ /**
+ *
+ * @param username ���������
+ * @param mode ������������
+ * @param organizationId ������������
+ * @param authorities ������������
+ * @return
+ */
+ public static UserContext create(String username,LoginMode mode,Integer organizationId, List<GrantedAuthority> authorities) {
+ if (StringUtils.isBlank(username)) throw new IllegalArgumentException("Username is blank: " + username);
+ return new UserContext(username, mode, organizationId, authorities);
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public List<GrantedAuthority> getAuthorities() {
+ return authorities;
+ }
+}
diff --git a/src/main/java/com/moral/security/model/token/AccessJwtToken.java b/src/main/java/com/moral/security/model/token/AccessJwtToken.java
new file mode 100644
index 0000000..28f2d96
--- /dev/null
+++ b/src/main/java/com/moral/security/model/token/AccessJwtToken.java
@@ -0,0 +1,30 @@
+package com.moral.security.model.token;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.jsonwebtoken.Claims;
+
+/**
+ * Raw representation of JWT Token.
+ *
+ * @author vladimir.stankovic
+ *
+ * May 31, 2016
+ */
+public final class AccessJwtToken implements JwtToken {
+ private final String rawToken;
+ @JsonIgnore
+ private Claims claims;
+
+ protected AccessJwtToken(final String token, Claims claims) {
+ this.rawToken = token;
+ this.claims = claims;
+ }
+
+ public String getToken() {
+ return this.rawToken;
+ }
+
+ public Claims getClaims() {
+ return claims;
+ }
+}
diff --git a/src/main/java/com/moral/security/model/token/JwtToken.java b/src/main/java/com/moral/security/model/token/JwtToken.java
new file mode 100644
index 0000000..dc47498
--- /dev/null
+++ b/src/main/java/com/moral/security/model/token/JwtToken.java
@@ -0,0 +1,5 @@
+package com.moral.security.model.token;
+
+public interface JwtToken {
+ String getToken();
+}
diff --git a/src/main/java/com/moral/security/model/token/JwtTokenFactory.java b/src/main/java/com/moral/security/model/token/JwtTokenFactory.java
new file mode 100644
index 0000000..6db2228
--- /dev/null
+++ b/src/main/java/com/moral/security/model/token/JwtTokenFactory.java
@@ -0,0 +1,93 @@
+package com.moral.security.model.token;
+
+import com.moral.security.config.JwtSettings;
+import com.moral.security.model.Scopes;
+import com.moral.security.model.UserContext;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * Factory class that should be always used to create {@link JwtToken}.
+ *
+ * @author vladimir.stankovic
+ *
+ * May 31, 2016
+ */
+@Component
+public class JwtTokenFactory {
+ private final JwtSettings settings;
+
+ @Autowired
+ public JwtTokenFactory(JwtSettings settings) {
+ this.settings = settings;
+ }
+
+ /**
+ * Factory method for issuing new JWT Tokens.
+ *
+ * @param userContext
+ * @return
+ */
+ public AccessJwtToken createAccessJwtToken(UserContext userContext) {
+ if (StringUtils.isBlank(userContext.getUsername()))
+ throw new IllegalArgumentException("Cannot create JWT Token without username");
+
+ if (userContext.getAuthorities() == null || userContext.getAuthorities().isEmpty())
+ throw new IllegalArgumentException("User doesn't have any privileges");
+
+ Claims claims = Jwts.claims().setSubject(userContext.getUsername());
+ claims.put("oid",userContext.getOrganizationId());
+ claims.put("mode",userContext.getMode());
+ claims.put("scopes", userContext.getAuthorities().stream().map(s -> s.toString()).collect(Collectors.toList()));
+
+ LocalDateTime currentTime = LocalDateTime.now();
+
+ String token = Jwts.builder()
+ .setClaims(claims)
+ .setIssuer(settings.getTokenIssuer())
+ .setIssuedAt(Date.from(currentTime.atZone(ZoneId.systemDefault()).toInstant()))
+ .setExpiration(Date.from(currentTime
+ .plusMinutes(settings.getTokenExpirationTime())
+ .atZone(ZoneId.systemDefault()).toInstant()))
+ .signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
+ .compact();
+
+ return new AccessJwtToken(token, claims);
+ }
+
+ public JwtToken createRefreshToken(UserContext userContext) {
+ if (StringUtils.isBlank(userContext.getUsername())) {
+ throw new IllegalArgumentException("Cannot create JWT Token without username");
+ }
+
+ LocalDateTime currentTime = LocalDateTime.now();
+
+ Claims claims = Jwts.claims().setSubject(userContext.getUsername());
+ claims.put("mode",userContext.getMode());
+// claims.put("scopes", Arrays.asList(Scopes.REFRESH_TOKEN.authority()));
+
+ String token = Jwts.builder()
+ .setClaims(claims)
+ .setIssuer(settings.getTokenIssuer())
+ .setId(UUID.randomUUID().toString())
+ .setIssuedAt(Date.from(currentTime.atZone(ZoneId.systemDefault()).toInstant()))
+ .setExpiration(Date.from(currentTime
+ .plusMinutes(settings.getRefreshTokenExpTime())
+ .atZone(ZoneId.systemDefault()).toInstant()))
+ .signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
+ .compact();
+
+ return new AccessJwtToken(token, claims);
+ }
+}
diff --git a/src/main/java/com/moral/security/model/token/RawAccessJwtToken.java b/src/main/java/com/moral/security/model/token/RawAccessJwtToken.java
new file mode 100644
index 0000000..b1d2bff
--- /dev/null
+++ b/src/main/java/com/moral/security/model/token/RawAccessJwtToken.java
@@ -0,0 +1,41 @@
+package com.moral.security.model.token;
+
+import com.moral.security.exceptions.JwtExpiredTokenException;
+import io.jsonwebtoken.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+
+public class RawAccessJwtToken implements JwtToken {
+ private static Logger logger = LoggerFactory.getLogger(RawAccessJwtToken.class);
+
+ private String token;
+
+ public RawAccessJwtToken(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Parses and validates JWT Token signature.
+ *
+ * @throws BadCredentialsException
+ * @throws JwtExpiredTokenException
+ *
+ */
+ public Jws<Claims> parseClaims(String signingKey) {
+ try {
+ return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(this.token);
+ } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException | SignatureException ex) {
+ logger.error("Invalid JWT Token", ex);
+ throw new BadCredentialsException("Invalid JWT token: ", ex);
+ } catch (ExpiredJwtException expiredEx) {
+ logger.info("JWT Token is expired", expiredEx);
+ throw new JwtExpiredTokenException(this, "JWT Token expired", expiredEx);
+ }
+ }
+
+ @Override
+ public String getToken() {
+ return token;
+ }
+}
diff --git a/src/main/java/com/moral/security/model/token/RefreshToken.java b/src/main/java/com/moral/security/model/token/RefreshToken.java
new file mode 100644
index 0000000..0f67cd0
--- /dev/null
+++ b/src/main/java/com/moral/security/model/token/RefreshToken.java
@@ -0,0 +1,65 @@
+package com.moral.security.model.token;
+
+import com.moral.security.model.Scopes;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import org.springframework.security.authentication.BadCredentialsException;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * RefreshToken
+ *
+ * @author vladimir.stankovic
+ *
+ * Aug 19, 2016
+ */
+@SuppressWarnings("unchecked")
+public class RefreshToken implements JwtToken {
+ private Jws<Claims> claims;
+
+ private RefreshToken(Jws<Claims> claims) {
+ this.claims = claims;
+ }
+
+ /**
+ * Creates and validates Refresh token
+ *
+ * @param token
+ * @param signingKey
+ *
+ * @throws BadCredentialsException
+ * @throws JwtExpiredTokenException
+ *
+ * @return
+ */
+ public static Optional<RefreshToken> create(RawAccessJwtToken token, String signingKey) {
+ Jws<Claims> claims = token.parseClaims(signingKey);
+
+ List<String> scopes = claims.getBody().get("scopes", List.class);
+ if (scopes == null || scopes.isEmpty()
+ || !scopes.stream().filter(scope -> Scopes.REFRESH_TOKEN.authority().equals(scope)).findFirst().isPresent()) {
+ return Optional.empty();
+ }
+
+ return Optional.of(new RefreshToken(claims));
+ }
+
+ @Override
+ public String getToken() {
+ return null;
+ }
+
+ public Jws<Claims> getClaims() {
+ return claims;
+ }
+
+ public String getJti() {
+ return claims.getBody().getId();
+ }
+
+ public String getSubject() {
+ return claims.getBody().getSubject();
+ }
+}
diff --git a/src/main/java/com/moral/service/AccountService.java b/src/main/java/com/moral/service/AccountService.java
index 289adcf..68e8371 100644
--- a/src/main/java/com/moral/service/AccountService.java
+++ b/src/main/java/com/moral/service/AccountService.java
@@ -2,6 +2,7 @@
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import com.moral.common.bean.PageBean;
import com.moral.entity.Account;
@@ -24,4 +25,5 @@
Integer getAccountCountByAccountName(String accountName);
+ Optional<Account> queryAccountByName(String accountName);
}
diff --git a/src/main/java/com/moral/service/DeviceService.java b/src/main/java/com/moral/service/DeviceService.java
index e40048a..707b487 100644
--- a/src/main/java/com/moral/service/DeviceService.java
+++ b/src/main/java/com/moral/service/DeviceService.java
@@ -3,6 +3,7 @@
import java.util.List;
import java.util.Map;
import com.moral.common.bean.PageBean;
+import com.moral.common.bean.PageResult;
import com.moral.entity.Device;
public interface DeviceService {
@@ -17,6 +18,8 @@
Device getDeviceByMac(String mac);
+ PageResult query(Integer orgId, String deviceName,Integer pageSize,Integer pageNo);
+
PageBean queryByPageBean(PageBean pageBean);
void deleteByIds(Integer[] ids);
diff --git a/src/main/java/com/moral/service/impl/AccountServiceImpl.java b/src/main/java/com/moral/service/impl/AccountServiceImpl.java
index be7b39a..d441f1f 100644
--- a/src/main/java/com/moral/service/impl/AccountServiceImpl.java
+++ b/src/main/java/com/moral/service/impl/AccountServiceImpl.java
@@ -7,15 +7,11 @@
import static org.apache.commons.lang3.StringUtils.isNumeric;
import static org.springframework.util.ObjectUtils.isEmpty;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import javax.annotation.Resource;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@@ -38,7 +34,8 @@
@Service
public class AccountServiceImpl implements AccountService {
-
+ @Resource
+ private BCryptPasswordEncoder encoder;
@Resource
private AccountMapper accountMapper;
@@ -47,7 +44,7 @@
@Resource
private OrganizationMapper organizationMapper;
-
+
@Override
public Map<String, Object> screenLogin(Map<String, Object> parameters) {
Map<String, Object> result = new HashMap<String, Object>();
@@ -147,7 +144,7 @@
if (ObjectUtils.isEmpty(account.getId())) {
account.setIsDelete(Constants.IS_DELETE_FALSE);
account.setCreateTime(new Date());
- account.setPassword(Crypto.md5(ResourceUtil.getValue("password")));
+ account.setPassword(encoder.encode(ResourceUtil.getValue("password")));
return accountMapper.insertSelective(account);
} else {
return accountMapper.updateByPrimaryKeySelective(account);
@@ -171,4 +168,10 @@
return accountMapper.selectCount(account);
}
+ @Override
+ public Optional<Account> queryAccountByName(String accountName) {
+ Account account = new Account();
+ account.setAccountName(accountName);
+ return Optional.ofNullable(accountMapper.selectOne(account));
+ }
}
diff --git a/src/main/java/com/moral/service/impl/DeviceServiceImpl.java b/src/main/java/com/moral/service/impl/DeviceServiceImpl.java
index 78cbbd7..eefb269 100644
--- a/src/main/java/com/moral/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/moral/service/impl/DeviceServiceImpl.java
@@ -4,8 +4,10 @@
import javax.annotation.Resource;
+import com.github.pagehelper.Page;
import com.moral.common.bean.Constants;
import com.moral.common.bean.PageBean;
+import com.moral.common.bean.PageResult;
import com.moral.common.util.ExampleUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -102,6 +104,18 @@
}
@Override
+ public PageResult query(Integer orgId, String deviceName, Integer pageSize, Integer pageNo) {
+ if(!ObjectUtils.isEmpty(pageSize)&&!ObjectUtils.isEmpty(pageNo)){
+ PageHelper.startPage(pageNo,pageSize);
+ }
+ List list = deviceMapper.selectByOrgIdAndDevName(orgId,deviceName);
+ if(list instanceof Page){
+ return new PageResult(((Page) list).getTotal(),list);
+ }
+ return new PageResult(null,list);
+ }
+
+ @Override
public PageBean queryByPageBean(PageBean pageBean) {
Example example = ExampleUtil.generateExample(ENTITY_CLASS,pageBean);
List<Example.Criteria> criteriaList = example.getOredCriteria();
diff --git a/src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java b/src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java
index fc0db0d..79cf204 100644
--- a/src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java
+++ b/src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java
@@ -9,11 +9,9 @@
import com.github.pagehelper.PageHelper;
import com.moral.common.bean.Constants;
import com.moral.common.bean.PageBean;
-import com.moral.common.util.ExampleUtil;
-import com.moral.common.util.MyBatisBaseMapUtil;
+import com.moral.common.util.*;
import org.springframework.stereotype.Service;
-import com.moral.common.util.ValidateUtil;
import com.moral.entity.MonitorPoint;
import com.moral.mapper.MonitorPointMapper;
import com.moral.service.MonitorPointService;
@@ -24,6 +22,8 @@
public class MonitorPointServiceImpl implements MonitorPointService {
@Resource
private MonitorPointMapper monitorPointMapper;
+ @Resource
+ RedisUtils redisUtils;
private static Class ENTITY_CLASS = MonitorPoint.class;
@Override
public List<MonitorPoint> getMonitorPointsByAreaName(Map<String, Object> parameters) {
@@ -32,7 +32,25 @@
}
@Override
public List<MonitorPoint> queryWithStateByMap(Map<String, Object> params){
- return monitorPointMapper.selectWithStateByMap(params);
+ List<MonitorPoint> monitorPointList = monitorPointMapper.selectByMap(params);
+ for(MonitorPoint monitorPoint:monitorPointList){
+ loadStateFromRedis(monitorPoint);
+ }
+ return monitorPointList;
+ }
+ private void loadStateFromRedis(MonitorPoint monitorPoint){
+ StringBuilder key = new StringBuilder();
+ key.append("*_").append(monitorPoint.getId()).append("_*");
+ List<Map> stateList = redisUtils.getList(key.toString(),Map.class);
+ int state = -1;
+ if(stateList!=null){
+ for (Map deviceState:stateList){
+ int s = Integer.parseInt(deviceState.get("state").toString());
+ state = s>state&&s<4?s:state;
+ }
+ }
+ state = state==-1?4:state;
+ monitorPoint.setState(state);
}
@Override
public PageBean queryByPageBean(PageBean pageBean) {
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index b76fb92..f15aa45 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -3,8 +3,15 @@
session-timeout: 30
tomcat.max-threads: 0
tomcat.uri-encoding: UTF-8
-
+spring.profiles: default
+moral.security.jwt:
+ tokenExpirationTime: 15 # Number of minutes
+ refreshTokenExpTime: 60 # Minutes
+ tokenIssuer: http://monitor.7drlb.com
+ tokenSigningKey: xm9EV6Hy5RAFL8EEACIDAwQus
spring:
+ thymeleaf:
+ cache: false
datasource:
url: jdbc:mysql://47.96.19.115:3306/monitor_db?characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
username: root
@@ -64,4 +71,5 @@
mybatis:
mapper-locations: classpath*:/mapper/*Mapper.xml
- config-location: classpath:/mapper/mybatis-config.xml
\ No newline at end of file
+ config-location: classpath:/mapper/mybatis-config.xml
+
diff --git a/src/main/resources/mapper/DeviceMapper.xml b/src/main/resources/mapper/DeviceMapper.xml
index fbe298a..cb2cba0 100644
--- a/src/main/resources/mapper/DeviceMapper.xml
+++ b/src/main/resources/mapper/DeviceMapper.xml
@@ -81,7 +81,7 @@
</if>
)
</select>
- <select id="getDeviceStatesByAccount" resultType="map">
+ <select id="getDeviceStatesByAccount" resultType="java.util.Map">
SELECT
COUNT( d.state ) count,
d.state
@@ -98,8 +98,16 @@
</if>
GROUP BY d.state
</select>
-
- <select id="getSensorsByDevice" resultType="map">
+ <select id="selectByOrgIdAndDevName" resultMap="BaseResultMap">
+ SELECT * from device dev
+ left join monitor_point mpt on dev.monitor_point_id = mpt.id
+ where
+ mpt.organization_id = #{orgId}
+ <if test="devName!=null and ''!=devName">
+ and dev.name like #{devName}
+ </if>
+ </select>
+ <select id="getSensorsByDevice" resultType="java.util.Map">
SELECT
s.`key`,
s.`name`
diff --git a/src/main/resources/mapper/MonitorPointMapper.xml b/src/main/resources/mapper/MonitorPointMapper.xml
index 652012a..ee6e6af 100644
--- a/src/main/resources/mapper/MonitorPointMapper.xml
+++ b/src/main/resources/mapper/MonitorPointMapper.xml
@@ -13,6 +13,7 @@
<result column="address" jdbcType="VARCHAR" property="address" />
<result column="is_delete" jdbcType="CHAR" property="isDelete" />
<result column="description" jdbcType="VARCHAR" property="description" />
+ <result column="state" jdbcType="INTEGER" property="state" />
<!-- ������������������������������ -->
<association property="areaNames" javaType="com.moral.entity.AreaNames">
<result column="province_name" property="provinceName" jdbcType="VARCHAR" />
@@ -100,10 +101,8 @@
AND mp.city_code = c.city_code
</if>
</select>
- <select id="selectWithStateByMap" parameterType="java.util.Map" resultMap="BaseResultMap">
-
- SELECT mpt.*,MAX(dev.state) as state from monitor_point mpt
- LEFT JOIN device dev on dev.monitor_point_id = mpt.id
+ <select id="selectByMap" parameterType="java.util.Map" resultMap="BaseResultMap">
+ SELECT mpt.* from monitor_point mpt
<where>
<if test="@com.moral.common.bean.Constants@isNotSpecialOrgId(orgId)">
mpt.organization_id = #{orgId,jdbcType=VARCHAR}
@@ -113,25 +112,7 @@
AND mpt.longitude > #{mapBounds.Le,jdbcType=NUMERIC}
AND mpt.latitude < #{mapBounds.Fe,jdbcType=NUMERIC}
AND mpt.latitude > #{mapBounds.Ke,jdbcType=NUMERIC}
- and state<4
- GROUP BY mpt.`id`
]]>
- </where>
- UNION
- SELECT mpt.*,MAX(dev.state) as state from monitor_point mpt
- LEFT JOIN device dev on dev.monitor_point_id = mpt.id
- <where>
- <if test="@com.moral.common.bean.Constants@isNotSpecialOrgId(orgId)">
- mpt.organization_id = #{orgId,jdbcType=VARCHAR}
- </if>
- <![CDATA[
- AND mpt.longitude < #{mapBounds.Ge,jdbcType=NUMERIC}
- AND mpt.longitude > #{mapBounds.Le,jdbcType=NUMERIC}
- AND mpt.latitude < #{mapBounds.Fe,jdbcType=NUMERIC}
- AND mpt.latitude > #{mapBounds.Ke,jdbcType=NUMERIC}
- and state>3
- GROUP BY mpt.`id`
- ]]>
</where>
</select>
</mapper>
\ No newline at end of file
diff --git a/src/main/resources/system/sysConfig.properties b/src/main/resources/system/sysConfig.properties
index cbc54af..d2a12c9 100644
--- a/src/main/resources/system/sysConfig.properties
+++ b/src/main/resources/system/sysConfig.properties
@@ -26,4 +26,5 @@
e18-standard=9
e19-standard=50
orgId=-1
-password=123456
\ No newline at end of file
+password=123456
+noFilters=login
\ No newline at end of file
diff --git a/src/main/webapp/js/moralmap.js b/src/main/webapp/js/moralmap.js
index e26429f..c28f4b8 100644
--- a/src/main/webapp/js/moralmap.js
+++ b/src/main/webapp/js/moralmap.js
@@ -360,29 +360,19 @@
var pageSize = option["pageSize"] || 20;
var pageNo = option["pageNo"] || 1;
var url = option['url'];
- url += "&page=" + pageNo;
- url += "&rows=" + pageSize;
+ url += "&pageNo=" + pageNo;
+ url += "&pageSize=" + pageSize;
+ console.log(url);
$.ajax({
type: "get",
cache: false,
url: url,
async: true,
- success: function(data) {
- if(data) {
- if(typeof data !== 'object' && typeof data === 'string') {
- try {
- data = $.parseJSON(data);
- } catch(e) {
- return;
- }
- }
- var rows = null;
- if(data['rows'] != undefined) {
- rows = data['rows'];
- } else {
- rows = data;
- }
- if(rows.length == 0) {
+ success: function(res) {
+ if(res!=null&&res.total!=null) {
+ debugger;
+ var rows = res.data;
+ if(rows==null||rows.length == 0) {
$(option['id']).html("������������������������������");
return;
}
@@ -417,7 +407,7 @@
outHtml += li;
}
outHtml += "</ul>";
- var total = data['total'];
+ var total = res['total'];
var totalPage = Math.ceil(total / pageSize);
if(totalPage > 1) {
outHtml += "<div id='page' class='page_div'></div>";
@@ -494,7 +484,7 @@
//��������������� ������Mark������
moralMap.Monitorpoint = function(option) {
var icon = {};
- icon["stateIcons"] = ["img/ico00.png", "img/ico01.png", "img/ico02.png", "img/ico03.png", "img/ico04.png"];
+ icon["stateIcons"] = ["/img/ico00.png", "/img/ico01.png", "/img/ico02.png", "/img/ico03.png", "/img/ico04.png"];
icon["width"] = 50;
icon["height"] = 50;
option["icon"] = icon;
diff --git a/src/main/webapp/view/map.jsp b/src/main/webapp/view/map.jsp
index 77896b8..6473019 100644
--- a/src/main/webapp/view/map.jsp
+++ b/src/main/webapp/view/map.jsp
@@ -264,7 +264,7 @@
function showEqus(obj) {
var params = moralMap['params'];
var mpoint = obj.currentTarget.getOption();
- var url = 'equipment/findAllEqu?mpId=' + mpoint['id'] + "&orgId=" + params['orgId'];
+ var url = 'get-devices?mpId=' + mpoint['id'] + "&orgId=" + params['orgId'];
listView.load(url);
moralMap.showPopupbox("#popup_box");
}
@@ -371,7 +371,7 @@
// if(endZoom>=moralMap.getZooMConfine()){//������������������������
// loadOverlays("getequipments",addOverEquipments);
// }else{
-// loadOverlays("getmonitorpoints",addOverMpoints);
+// loadOverlays("get-monitorpoints",addOverMpoints);
// }
// moralMap.closePopupbox("#popup_box");
});
@@ -383,7 +383,7 @@
if(endZoom>=moralMap.getZooMConfine()){//������������������������
loadOverlays("getequipments",addOverEquipments);
}else{
- loadOverlays("getmonitorpoints",addOverMpoints);
+ loadOverlays("get-monitorpoints",addOverMpoints);
}
moralMap.closePopupbox("#popup_box");
});
@@ -392,7 +392,7 @@
if(endZoom>=moralMap.getZooMConfine()){//������������������������
loadOverlays("getequipments",addOverEquipments);
}else{
- loadOverlays("getmonitorpoints",addOverMpoints);
+ loadOverlays("get-monitorpoints",addOverMpoints);
}
moralMap.closePopupbox("#popup_box");
});
@@ -401,7 +401,7 @@
function(e) {
var param = encodeURI($("#searchParam").val());
moralMap.showPopupbox("#popup_box");
- var url = 'equipment/findAllEqu?name=' + param + "&orgId=" + params['orgId'];
+ var url = 'get-devices-for-popup?name=' + param + "&orgId=" + params['orgId'];
listView.load(url);
}
)
diff --git a/src/test/java/com/moral/JavaBeanToJsonOutPrint.java b/src/test/java/com/moral/JavaBeanToJsonOutPrint.java
index fbc1ff3..8b9de9d 100644
--- a/src/test/java/com/moral/JavaBeanToJsonOutPrint.java
+++ b/src/test/java/com/moral/JavaBeanToJsonOutPrint.java
@@ -6,8 +6,11 @@
import com.moral.entity.Device;
import com.moral.entity.DeviceAdjustValue;
import com.moral.entity.alarm.AlarmConfig;
+import com.moral.security.auth.login.LoginMode;
+import com.moral.security.model.UserContext;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -15,7 +18,7 @@
public class JavaBeanToJsonOutPrint {
@Test
public void jsonOutPrintTest(){
- DeviceAdjustValue adjustValue = new DeviceAdjustValue();
+ UserContext userContext = UserContext.create("312", LoginMode.Andriod,1,new ArrayList<>());
// adjustValue.setCreateTime(new Date());
// adjustValue.setUpdateTime(new Date());
// adjustValue.setId(0);
@@ -23,12 +26,10 @@
// value.put("e1", (float) 1.2);
// adjustValue.setValue(value);
String json = "{\"createTime\":1516342989358,\"deviceId\":null,\"id\":0,\"updateTime\":1516342989358,\"value\":{\"e1\":1.2}}";
- Map map = JSON.parseObject("{\"e1\":0.0}");
-// String json = JSON.toJSONString(new Device(),
-// SerializerFeature.WriteMapNullValue
-// );
+// Map map = JSON.parseObject("{\"e1\":0.0}");
+ String json1 = JSON.toJSONString(userContext);
System.out.printf("\n\n\n\n");
- System.out.printf(json);
+ System.out.printf(json1);
System.out.printf("\n\n\n\n");
}
}
--
Gitblit v1.8.0