package pwc.taxtech.atms.web.controller; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestBody; 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.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.util.UriComponentsBuilder; import com.alibaba.fastjson.JSON; import pwc.taxtech.atms.common.CheckState; import pwc.taxtech.atms.dto.AtmsTokenDto; import pwc.taxtech.atms.dto.LoginInputDto; import pwc.taxtech.atms.dto.LoginOutputDto; import pwc.taxtech.atms.dto.OperationResultDto; import pwc.taxtech.atms.dto.OrganizationStructureDto; import pwc.taxtech.atms.web.AtmsWebSettings; /** @see PwC.Tax.Tech.Atms.Web\Controllers\AccountController.cs */ @Controller @RequestMapping("/Account") public class AccountController { private static Logger logger = LoggerFactory.getLogger(AccountController.class); @Autowired private AtmsWebSettings atmsWebSettings; @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/LogOn", method = RequestMethod.POST) public @ResponseBody LoginOutputDto login(@RequestBody LoginInputDto input, HttpServletResponse response) throws UnsupportedEncodingException { logger.debug("login start"); if (input == null || !StringUtils.hasText(input.getEmail())) { LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("Please enter the valid user name for your account."); errorReturn.setCheckState(CheckState.EmptyUserName.value()); logger.debug("空的用户名"); return errorReturn; } if (!StringUtils.hasText(input.getPassword())) { LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("Please enter your password."); errorReturn.setCheckState(CheckState.EmptyPassword.value()); logger.debug("空的密码"); return errorReturn; } OperationResultDto<LoginOutputDto> operationResultDto = null; try { long start = System.currentTimeMillis(); logger.debug("准备调用atms-api的login接口"); operationResultDto = callApiUserLogin(input.getEmail(), input.getPassword()); logger.debug("atms-api的login接口返回,用时[{}ms]", System.currentTimeMillis() - start); } catch (RestClientException e) { logger.error("调用atms-api的login接口出错:" + e, e); LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("Generate auth token failed, please check if WebApi is running"); errorReturn.setCheckState(CheckState.UnKnown.value()); return errorReturn; } catch (Exception e) { logger.error("Unknown error occures, 调用atms-api的login接口出错:" + e, e); LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("Unknown error occures " + e.getMessage()); errorReturn.setCheckState(CheckState.UnKnown.value()); return errorReturn; } Assert.notNull(operationResultDto.getResult(), "Null value of operationResultDto.getResult()"); LoginOutputDto resultLoginOutputDto = operationResultDto.getData(); if (!operationResultDto.getResult()) { logger.info("登录失败, email:{}, password.length:{}", input.getEmail(), input.getPassword().length()); return resultLoginOutputDto; } logger.info("登录成功, email:{}, password.length:{}", input.getEmail(), input.getPassword().length()); if (!CheckState.Success.value().equals(resultLoginOutputDto.getCheckState())) { LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("服务端返回状态异常"); logger.info("登录成功但是CheckState有异常, email:{}, password.length:{}, data.checkState:{}", input.getEmail(), input.getPassword().length(), resultLoginOutputDto.getCheckState()); errorReturn.setCheckState(CheckState.UnKnown.value()); return errorReturn; } // CheckResult checkResult = validate(input) // UserDto dummyUser = new UserDto(); // dummyUser.setUniqueId("05cae670-0b10-4b60-9697-04aed2c0da85"); // dummyUser.setLoginName(input.getEmail()); // dummyUser.setPassword(input.getPassword()); // dummyUser.setHasValidPeriod(false); // LogOnModel loginModel = new LogOnModel(); // loginModel.setCheckState(CheckState.SUCCESS.value()); // loginModel.setMessage("login success"); // loginModel.setUser(dummyUser); // loginModel.setApiHost(apiUrl); // AtmsTokenDto cookieModel = new AtmsTokenDto(); // cookieModel.setAccess_token( // "5VEIJ9Nv_M6ppQlgepJcCYXhZPkY_pcgbKpVt-P4ZOOqpFWQ0DgMtymbOw26jrZYoFnoQiyzmv29wpeBWaAHnE4nYRNZ_5ZsvG_59kYh_bWd6c42qaiPOdZQN_s9VZjqEfdn96Ucfa-gAbKJANMUiewrzecl2v4ugMlid0XuzcKYaKsceESR36pfRDMrEf5Q7xqx-A"); // cookieModel.setToken_type("bearer"); // cookieModel.setExpires_in(1200000L); // cookieModel.setApi_host(apiUrl); // cookieModel.setVat_api_host("https://cnshaappuwv023:30005"); // cookieModel.setTp_url("https://cnshaappuwv023:35001"); // cookieModel.setVersion("1.0.0.0"); // cookieModel.setUser_name("admin"); // cookieModel.setLocal_name("admin"); // cookieModel.setNeed_change_password(false); // cookieModel.setIs_external_user(false); // cookieModel.setUser_id("66933E7B-DA75-4B2E-B7D6-AB65DCA20D50"); AtmsTokenDto token = resultLoginOutputDto.getToken(); if (token == null || !StringUtils.hasText(token.getAccess_token())) { LoginOutputDto errorReturn = new LoginOutputDto(); errorReturn.setMessage("服务端返回Token异常"); logger.info("登录成功但是Token有异常, email:{}, password.length:{}, data.checkState:{}", input.getEmail(), input.getPassword().length(), resultLoginOutputDto.getCheckState()); errorReturn.setCheckState(CheckState.UnKnown.value()); return errorReturn; } // 字段api_host应该由atms-web来定义 token.setApi_host(atmsWebSettings.getApiUrl()); resultLoginOutputDto.setApiHost(atmsWebSettings.getApiUrl()); String cookieString = JSON.toJSONString(resultLoginOutputDto.getToken()); String cookieValue = URLEncoder.encode(cookieString, "UTF-8"); Cookie cookie = new Cookie("AtmsApiToken", cookieValue); cookie.setPath("/"); // TODO get maxAge from properties cookie.setMaxAge(atmsWebSettings.getCookieMaxAgeSeconds()); response.addCookie(cookie); // 在输出的json中删除Token对象,因为前端不需要这个字段 resultLoginOutputDto.setToken(null); return resultLoginOutputDto; } private OperationResultDto<LoginOutputDto> callApiUserLogin(String email, String password) { String url = atmsWebSettings.getApiUrl() + "/api/v1/user/login"; logger.debug("Print url:{}", url); ParameterizedTypeReference<OperationResultDto<LoginOutputDto>> parameterizedTypeReference = new ParameterizedTypeReference<OperationResultDto<LoginOutputDto>>() { }; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); LoginInputDto loginInputDto = new LoginInputDto(); loginInputDto.setEmail(email); loginInputDto.setPassword(password); HttpEntity<LoginInputDto> requestEntity = new HttpEntity<>(loginInputDto, headers); ResponseEntity<OperationResultDto<LoginOutputDto>> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, parameterizedTypeReference); Assert.notNull(responseEntity, "Null responseEntity"); Assert.notNull(responseEntity.getBody(), "Null responseEntity.body"); OperationResultDto<LoginOutputDto> operationResultDto = responseEntity.getBody(); logger.debug("print OperationResultDto<LoginOutputDto> as JSON:{}", JSON.toJSONString(operationResultDto, true)); // Assert.state(operationResultDto.getResult() != null && // operationResultDto.getResult(), // "operationResultDto.getResult() is false"); return operationResultDto; } @RequestMapping(value = { "/LogOut", "/Logout" }, produces = "text/html;charset=UTF-8") public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(false); if (session != null) { // 删除会话 session.invalidate(); } Cookie cookie = new Cookie("AtmsApiToken", ""); cookie.setPath("/"); cookie.setMaxAge(0); // 删除Cookie response.addCookie(cookie); return new ModelAndView("logon"); } @RequestMapping(value = { "/LogOn", "/Logon" }, produces = "text/html;charset=UTF-8", method = RequestMethod.GET) public ModelAndView LogOnGet(HttpServletRequest request, HttpServletResponse response) { return new ModelAndView("logon"); } @RequestMapping(value = "/PingApi", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public OperationResultDto<OrganizationStructureDto> pingApi() { String url = atmsWebSettings.getApiUrl() + "/PingApi"; logger.debug("Print url:{}", url); ParameterizedTypeReference<OperationResultDto<OrganizationStructureDto>> parameterizedTypeReference = new ParameterizedTypeReference<OperationResultDto<OrganizationStructureDto>>() { }; ResponseEntity<OperationResultDto<OrganizationStructureDto>> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, parameterizedTypeReference); return responseEntity.getBody(); } @RequestMapping(value = "/CheckLoginStatus", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public Boolean checkLoginStatus(@CookieValue(value = "AtmsApiToken", required = false) String atmsApiToken, HttpServletResponse response) throws UnsupportedEncodingException { if (StringUtils.hasText(atmsApiToken)) { Cookie newCookie = new Cookie("AtmsApiToken", URLEncoder.encode(atmsApiToken, "UTF-8")); newCookie.setPath("/"); newCookie.setMaxAge(atmsWebSettings.getCookieMaxAgeSeconds()); response.addCookie(newCookie); return true; } return false; } @SuppressWarnings("rawtypes") @RequestMapping(value = "/ForgetPassword", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public OperationResultDto<Object> forgetPassword(@RequestBody(required = false) LoginInputDto input) { logger.debug("enter ForgetPassword"); Assert.notNull(input, "Null input object"); Assert.hasText(input.getEmail(), "Empty email"); logger.debug("print email:{}", input.getEmail()); final String targetApi = "/api/v1/Account/ForgetPassword"; String url = atmsWebSettings.getApiUrl() + targetApi; UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); builder.queryParam("mail", input.getEmail()); builder.build().encode().toUriString(); try { OperationResultDto operationResultDto = restTemplate.getForObject(url, OperationResultDto.class); if (operationResultDto != null && operationResultDto.getResult() != null && operationResultDto.getResult()) { logger.info("return success by target api [{}]: {}", targetApi); return new OperationResultDto<>(true); } else { logger.error("return false by target api [{}]: {}", targetApi); return new OperationResultDto<>(false); } } catch (Exception e) { logger.error("error calling target api [{}]: {}", targetApi, e.toString()); return new OperationResultDto<>(false); } } }