fengxiang
2018-02-01 cd16757f2cd963749850d6f8897381a8b7a849ef
安全模块
4 files deleted
35 files added
20 files modified
1930 ■■■■ changed files
src/main/java/com/moral/common/util/Crypto.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/moral/config/MvcConfiguration.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/moral/controller/MapController.java 36 ●●●● patch | view | raw | blame | history
src/main/java/com/moral/entity/Account.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/entity/MonitorPoint.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/entity/Role.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/mapper/DeviceMapper.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/moral/mapper/MonitorPointMapper.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/moral/mapper/type/AdjustValueTypeHandle.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/AuthorizationServerConfiguration.java 60 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/CustomCorsFilter.java 33 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/ResourceServerConfiguration.java 49 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/RestAuthenticationEntryPoint.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/WebMvcConfiguration.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/WebSecurityConfiguration.java 89 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/JwtAuthenticationToken.java 61 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java 68 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java 64 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java 74 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java 53 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java 74 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginMode.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java 84 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/auth/login/LoginRequest.java 40 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/common/ErrorCode.java 27 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/common/ErrorResponse.java 52 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/common/WebUtil.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/config/JwtSettings.java 59 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/config/PasswordEncoderConfig.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/config/WebSecurityConfig.java 118 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/endpoint/ProfileEndpoint.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java 82 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/exceptions/InvalidJwtToken.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java 29 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/Scopes.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/UserContext.java 58 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/token/AccessJwtToken.java 30 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/token/JwtToken.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/token/JwtTokenFactory.java 93 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/token/RawAccessJwtToken.java 41 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/security/model/token/RefreshToken.java 65 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/service/AccountService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/service/DeviceService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/service/impl/AccountServiceImpl.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/service/impl/DeviceServiceImpl.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/com/moral/service/impl/MonitorPointServiceImpl.java 26 ●●●● patch | view | raw | blame | history
src/main/resources/application.yml 10 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/DeviceMapper.xml 14 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/MonitorPointMapper.xml 25 ●●●● patch | view | raw | blame | history
src/main/resources/system/sysConfig.properties 1 ●●●● patch | view | raw | blame | history
src/main/webapp/js/moralmap.js 30 ●●●●● patch | view | raw | blame | history
src/main/webapp/view/map.jsp 10 ●●●● patch | view | raw | blame | history
src/test/java/com/moral/JavaBeanToJsonOutPrint.java 13 ●●●● patch | view | raw | blame | history
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));
    }
}
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();
    }
}
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,10 +40,12 @@
    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);
        if(account!=null&&regionName!=null){
        Object sensors = sensorService.queryAll();
        JSONObject params = new JSONObject();
        params.put("regionCode",code);
@@ -49,8 +56,17 @@
        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);
    }
}
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;
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;
src/main/java/com/moral/entity/Role.java
New file
@@ -0,0 +1,8 @@
package com.moral.entity;
import lombok.Data;
@Data
public class Role {
   private String name;
}
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);
}
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);
}
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;
src/main/java/com/moral/security/AuthorizationServerConfiguration.java
File was deleted
src/main/java/com/moral/security/CustomCorsFilter.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/ResourceServerConfiguration.java
File was deleted
src/main/java/com/moral/security/RestAuthenticationEntryPoint.java
New file
@@ -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");
    }
}
src/main/java/com/moral/security/WebMvcConfiguration.java
File was deleted
src/main/java/com/moral/security/WebSecurityConfiguration.java
File was deleted
src/main/java/com/moral/security/auth/JwtAuthenticationToken.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/auth/jwt/JwtAuthenticationProvider.java
New file
@@ -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));
    }
}
src/main/java/com/moral/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/auth/jwt/SkipPathRequestMatcher.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java
New file
@@ -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());
    }
}
src/main/java/com/moral/security/auth/jwt/extractor/TokenExtractor.java
New file
@@ -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);
}
src/main/java/com/moral/security/auth/jwt/verifier/BloomFilterTokenVerifier.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/auth/jwt/verifier/TokenVerifier.java
New file
@@ -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);
}
src/main/java/com/moral/security/auth/login/LoginAuthenticationProvider.java
New file
@@ -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));
    }
}
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationFailureHandler.java
New file
@@ -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));
    }
}
src/main/java/com/moral/security/auth/login/LoginAwareAuthenticationSuccessHandler.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/auth/login/LoginMode.java
New file
@@ -0,0 +1,5 @@
package com.moral.security.auth.login;
public enum LoginMode {
    Web,Screen,Andriod,Apple
}
src/main/java/com/moral/security/auth/login/LoginProcessingFilter.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/auth/login/LoginRequest.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/common/ErrorCode.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/common/ErrorResponse.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/common/WebUtil.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/config/JwtSettings.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/config/PasswordEncoderConfig.java
New file
@@ -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();
    }
}
src/main/java/com/moral/security/config/WebSecurityConfig.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/endpoint/ProfileEndpoint.java
New file
@@ -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();
    }
}
src/main/java/com/moral/security/endpoint/RefreshTokenEndpoint.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/exceptions/AuthMethodNotSupportedException.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/exceptions/InvalidJwtToken.java
New file
@@ -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;
}
src/main/java/com/moral/security/exceptions/JwtExpiredTokenException.java
New file
@@ -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();
    }
}
src/main/java/com/moral/security/model/Scopes.java
New file
@@ -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();
    }
}
src/main/java/com/moral/security/model/UserContext.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/model/token/AccessJwtToken.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/model/token/JwtToken.java
New file
@@ -0,0 +1,5 @@
package com.moral.security.model.token;
public interface JwtToken {
    String getToken();
}
src/main/java/com/moral/security/model/token/JwtTokenFactory.java
New file
@@ -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);
    }
}
src/main/java/com/moral/security/model/token/RawAccessJwtToken.java
New file
@@ -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;
    }
}
src/main/java/com/moral/security/model/token/RefreshToken.java
New file
@@ -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();
    }
}
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);
}
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);
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;
@@ -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));
    }
}
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();
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) {
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
@@ -65,3 +72,4 @@
mybatis:
  mapper-locations: classpath*:/mapper/*Mapper.xml
  config-location: classpath:/mapper/mybatis-config.xml
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` 
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,24 +112,6 @@
            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>
src/main/resources/system/sysConfig.properties
@@ -27,3 +27,4 @@
e19-standard=50
orgId=-1
password=123456
noFilters=login
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;
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); 
        }
    )
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");
    }
}