diff --git a/box-bps/src/main/java/com/ruoyi/bps/controller/ExpSubsPushApiController.java b/box-bps/src/main/java/com/ruoyi/bps/controller/ExpSubsPushApiController.java index 02e7cc63e..b33d9f2aa 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/controller/ExpSubsPushApiController.java +++ b/box-bps/src/main/java/com/ruoyi/bps/controller/ExpSubsPushApiController.java @@ -3,16 +3,21 @@ package com.ruoyi.bps.controller; import com.kuaidi100.sdk.response.SubscribeResp; import com.ruoyi.bps.domain.ExpSubscribe; import com.ruoyi.bps.service.IExpSubsPushApiService; +import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.enums.BusinessType; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * 接受快递推送信息的API接口Controller @@ -20,16 +25,16 @@ import javax.servlet.http.HttpServletRequest; * @author box * @date 2021-05-13 */ -@Api("快递信息订阅推送") +@Api(value = "快递信息订阅推送",tags = "快递订阅接口") @RestController -@RequestMapping("/anon") +/*@RequestMapping("/anon")*/ public class ExpSubsPushApiController extends BaseController { @Autowired IExpSubsPushApiService expSubsPushApiService; //推送 @CrossOrigin - @PostMapping("/subscribeCallBackUrl") + @PostMapping("anon/subscribeCallBackUrl") @ApiOperation("快递信息订阅推送接受") public SubscribeResp SubscribeCallBackUrl(HttpServletRequest request) { return expSubsPushApiService.ExpressSubscribeCallBackUrl(request); @@ -37,10 +42,25 @@ public class ExpSubsPushApiController extends BaseController { //订阅 @CrossOrigin - @PostMapping("/subscribe") + @PostMapping("anon/subscribe") public SubscribeResp Subscribe(ExpSubscribe expSubscribe){ return expSubsPushApiService.ExpressSubscribe(expSubscribe); } + //接受topgp订阅, + @Log(title = "快递订阅", businessType = BusinessType.OTHER) + @CrossOrigin + @ApiOperation(value="topgp订阅快递",notes = "request body格式: {\"deliveryNo\":\"S301-2108020001\",\"expressNo\":\"300444235610\",\"company\":\"annengwuliu\",\"phone\":\"13800138000\"}") + @ApiImplicitParams({ + @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "requestJson", value = "请求json",required = true, paramType = "body", dataType = "String", dataTypeClass = String.class) + }) + + @PostMapping("api/express/topgpSubscribe") + public String topgpSubscribe(HttpServletRequest request, HttpServletResponse response) throws IOException { + return expSubsPushApiService.ExpressSubscribeWithTopgp(request); + } + + } diff --git a/box-bps/src/main/java/com/ruoyi/bps/controller/FrForCrTopgpController.java b/box-bps/src/main/java/com/ruoyi/bps/controller/FrForCrTopgpController.java index c0d8f02a3..ea61ca9ac 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/controller/FrForCrTopgpController.java +++ b/box-bps/src/main/java/com/ruoyi/bps/controller/FrForCrTopgpController.java @@ -7,34 +7,39 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.List; import java.util.Map; +@Api(tags = "TOPGP使用帆软报表接口") @RestController public class FrForCrTopgpController { @Autowired private TopgpDdlService topgpDdlService; //访问 ../anon/bps/frforcr/topprod时,使用topprod + @ApiOperation("TOPPROD正式区访问") + @ApiImplicitParam(name = "jsonString", value = "Json字符串", paramType = "body", dataType = "String", dataTypeClass = String.class) @CrossOrigin @Log(title = "CSFR412_CR报表_TOPPROD", businessType = BusinessType.DROP) - @RequestMapping("/anon/bps/frforcr/topprod") + @PostMapping("/anon/bps/frforcr/topprod") @DataSource(value = DataSourceType.TOPPRODDSREPORT) public AjaxResult frforcrtopprod(@RequestBody Map map){ return frforcrtoppgp(map); } //访问../anon/bps/frforcr/topprod时,使用toptest实例 + @ApiOperation("TOPTEST正式区访问") + @ApiImplicitParam(name = "jsonString", value = "Json字符串", paramType = "body", dataType = "String", dataTypeClass = String.class) @CrossOrigin @Log(title = "CSFR412_CR报表_TOPTEST", businessType = BusinessType.DROP) - @RequestMapping("/anon/bps/frforcr/toptest") + @PostMapping("/anon/bps/frforcr/toptest") @DataSource(value = DataSourceType.TOPTESTDSREPORT) public AjaxResult frforcrtoptest(@RequestBody Map map){ return frforcrtoppgp(map); diff --git a/box-bps/src/main/java/com/ruoyi/bps/service/IExpSubsPushApiService.java b/box-bps/src/main/java/com/ruoyi/bps/service/IExpSubsPushApiService.java index 5867116de..f47f834de 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/service/IExpSubsPushApiService.java +++ b/box-bps/src/main/java/com/ruoyi/bps/service/IExpSubsPushApiService.java @@ -4,8 +4,15 @@ import com.ruoyi.bps.domain.ExpSubscribe; import com.kuaidi100.sdk.response.SubscribeResp; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; public interface IExpSubsPushApiService { + + /** + * 向快递100推送订阅请求 + * @param expSubscribe + * @return + */ public SubscribeResp ExpressSubscribe(ExpSubscribe expSubscribe); /** @@ -19,4 +26,11 @@ public interface IExpSubsPushApiService { * */ public SubscribeResp ExpressSubscribeCallBackUrl(HttpServletRequest request); + + /** + * 获取Topgp推送的快递信息,向快递100推送订阅请求 + * @param request + * @return + */ + public String ExpressSubscribeWithTopgp(HttpServletRequest request) throws IOException; } diff --git a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpSubsPushApiServiceImpl.java b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpSubsPushApiServiceImpl.java index 50b3ede50..ac794b775 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpSubsPushApiServiceImpl.java +++ b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpSubsPushApiServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.bps.service.impl; +import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.kuaidi100.sdk.api.Subscribe; import com.kuaidi100.sdk.contant.ApiInfoConstant; @@ -12,7 +13,6 @@ import com.kuaidi100.sdk.response.SubscribePushData; import com.kuaidi100.sdk.response.SubscribePushParamResp; import com.kuaidi100.sdk.response.SubscribePushResult; import com.kuaidi100.sdk.response.SubscribeResp; -import com.kuaidi100.sdk.utils.PropertiesReader; import com.kuaidi100.sdk.utils.SignUtils; import com.ruoyi.bps.domain.ExpSubsPushResp; import com.ruoyi.bps.domain.ExpSubscribe; @@ -20,23 +20,30 @@ import com.ruoyi.bps.service.IExpSubsPushApiService; import com.ruoyi.bps.service.IExpSubsPushRespService; import com.ruoyi.bps.service.IExpSubscribeService; import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Service public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { - String key = PropertiesReader.get("key"); + /*String key = PropertiesReader.get("key"); String customer = PropertiesReader.get("customer"); String secret = PropertiesReader.get("secret"); String siid = PropertiesReader.get("siid"); String userid = PropertiesReader.get("userid"); String tid = PropertiesReader.get("tid"); String secret_key = PropertiesReader.get("secret_key"); - String secret_secret = PropertiesReader.get("secret_secret"); + String secret_secret = PropertiesReader.get("secret_secret"); */ + @Value("${express.key}") + private String key; @Autowired private IExpSubsPushRespService expSubsPushRespService; @@ -50,6 +57,10 @@ public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { */ @Override public SubscribeResp ExpressSubscribe(ExpSubscribe expSubscribe) { + + String loginFrom= expSubscribe.getSalt(); + String subscribeFrom= StringUtils.isNotEmpty(loginFrom)?loginFrom.equals("topgp")?"topgp":"localhost":"localhost"; + SubscribeParameters subscribeParameters = new SubscribeParameters(); SubscribeResp subscribeResp = new SubscribeResp(); subscribeParameters.setCallbackurl("http://report.bpsemi.cn:8081/it_war/anon/subscribeCallBackUrl"); @@ -68,7 +79,7 @@ public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { IBaseClient subscribe = new Subscribe(); try{ HttpResult httpResult= subscribe.execute(subscribeReq); - System.out.println(httpResult); + //System.out.println(httpResult); subscribeResp= new Gson().fromJson(httpResult.getBody(),SubscribeResp.class); }catch (Exception e) { @@ -85,13 +96,13 @@ public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { newExpSubscribe.setCompany(expSubscribe.getCompany()); newExpSubscribe.setNumber(expSubscribe.getNumber()); newExpSubscribe.setPhone(expSubscribe.getPhone()); - newExpSubscribe.setSalt("bpsemi"); + newExpSubscribe.setSalt(subscribeFrom); //偷懒,把请求来源记录到salt栏位,不再增加exp_subscribe字段了。。以后找时间改吧 newExpSubscribe.setSubscribeTime(DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:ss")); newExpSubscribe.setResult((subscribeResp.isResult())?"true":"false"); newExpSubscribe.setReturnCode(subscribeResp.getReturnCode()); newExpSubscribe.setMessage(subscribeResp.getMessage()); - ExpSubscribe queryExpSubscribe = new ExpSubscribe(); + /*ExpSubscribe queryExpSubscribe = new ExpSubscribe(); queryExpSubscribe.setCompany(expSubscribe.getCompany()); queryExpSubscribe.setNumber(expSubscribe.getNumber()); queryExpSubscribe.setResult(expSubscribe.getResult()); @@ -107,7 +118,9 @@ public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { }else { //如果数据库中没有快递单号+快递公司编码,则更插入新记录 expSubscribeService.insertExpSubscribe(newExpSubscribe); - } + }*/ + //20210802 无论系统里有没有记录,都会记录本次推送。 + expSubscribeService.insertExpSubscribe(newExpSubscribe); //返回订阅结果 return subscribeResp; @@ -247,11 +260,62 @@ public class ExpSubsPushApiServiceImpl implements IExpSubsPushApiService { str+="\r\n"; } } - System.out.println(str); + //System.out.println(str); return str; } + /** + * 获取Topgp推送的快递信息,向快递100推送订阅请求 + * + * @param request + * @return + */ + @Override + public String ExpressSubscribeWithTopgp(HttpServletRequest request) throws IOException { + //获取httpServletRequest传过来的Json字符串,并进行解析 + JSONObject contentJson= JSONObject.parseObject(ServletUtils.getRequestContent(request)); + String deliveryNo= contentJson.getString("deliveryNo"); + String expressNo = contentJson.getString("expressNo"); + String company = contentJson.getString("company"); + String phone = contentJson.getString("phone"); + //如果出货单号或者快递单号为空,则返回错误信息,并写入Logo + if(StringUtils.isEmpty(deliveryNo) || StringUtils.isEmpty(expressNo)){ + SubscribeResp subscribeResp=new SubscribeResp(); + subscribeResp.setMessage("快递单号或出货单号为空"); + subscribeResp.setResult(false); + subscribeResp.setReturnCode("700"); + + Map map=new HashMap<>(); + map.put("subscribeResp",subscribeResp); + map.put("deliveryNo",deliveryNo); + map.put("expressNo",expressNo); + //写入Logo + //todo + + //返回错误信息 + return JSONObject.toJSONString(map); + + } + //向快递100推送订阅请求 + ExpSubscribe expSubscribe=new ExpSubscribe(); + expSubscribe.setNumber(expressNo); + expSubscribe.setCompany(company); + expSubscribe.setPhone(phone); + expSubscribe.setSalt("topgp"); //偷懒,把请求来源记录到salt栏位,不再增加exp_subscribe字段了。。以后找时间改吧 + SubscribeResp subscribeResp= ExpressSubscribe(expSubscribe); + + /*Object object = JSONObject.toJSON(subscribeResp); + Map map=JSONObject.parseObject(object.toString(), Map.class);*/ + Map map= new HashMap<>(); + map.put("expSubscribe",subscribeResp); + map.put("deliveryNo",deliveryNo); + map.put("expressNo",expressNo); + return JSONObject.toJSONString(map); + } + + + } diff --git a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressInfoServiceImpl.java b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressInfoServiceImpl.java index 6e1f80630..e9f6093cf 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressInfoServiceImpl.java +++ b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressInfoServiceImpl.java @@ -21,6 +21,7 @@ import com.kuaidi100.sdk.response.QueryTrackResp; import com.kuaidi100.sdk.utils.PropertiesReader; import com.kuaidi100.sdk.utils.SignUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -37,13 +38,6 @@ import java.util.List; public class ExpressInfoServiceImpl implements IExpressInfoService { /* - String key = "Jydbrxsm2311"; - String customer = "2DD48B3469B82F2B7700569093AB792B"; - String secret = "8781ed9b35a7438499eb02fee915915a"; - String userid = "2a62da2192c24d17a943ff78ee64f8c6"; - - */ - String key = PropertiesReader.get("key"); String customer = PropertiesReader.get("customer"); String secret = PropertiesReader.get("secret"); @@ -52,6 +46,13 @@ public class ExpressInfoServiceImpl implements IExpressInfoService String tid = PropertiesReader.get("tid"); String secret_key = PropertiesReader.get("secret_key"); String secret_secret = PropertiesReader.get("secret_secret"); + */ + @Value("${express.key}") + private String key; + + @Value("${express.customer}") + private String customer; + @@ -132,7 +133,7 @@ public class ExpressInfoServiceImpl implements IExpressInfoService //如果没有输入快递公司编号,则查询快递公司编号 if(StringUtils.isEmpty(com)){ if(AutoGetExpressCom(nu)==null){ - callbackExpressInfo.setData("根据快递单号查询不到快递公司,请确认快递单号是否正确!"); + callbackExpressInfo.setData("请提供要查询的快递所属物流公司编号!"); return callbackExpressInfo; } com=AutoGetExpressCom(nu).getComCode(); diff --git a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressServiceImpl.java b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressServiceImpl.java index 7be4e0eb5..b71b0370a 100644 --- a/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressServiceImpl.java +++ b/box-bps/src/main/java/com/ruoyi/bps/service/impl/ExpressServiceImpl.java @@ -14,6 +14,7 @@ import com.kuaidi100.sdk.utils.SignUtils; import com.ruoyi.bps.service.IExpressService; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -27,14 +28,21 @@ public class ExpressServiceImpl implements IExpressService { String secret = "8781ed9b35a7438499eb02fee915915a"; String userid = "2a62da2192c24d17a943ff78ee64f8c6"; */ - String key = PropertiesReader.get("key"); + /*String key = PropertiesReader.get("key"); String customer = PropertiesReader.get("customer"); String secret = PropertiesReader.get("secret"); String siid = PropertiesReader.get("siid"); String userid = PropertiesReader.get("userid"); String tid = PropertiesReader.get("tid"); String secret_key = PropertiesReader.get("secret_key"); - String secret_secret = PropertiesReader.get("secret_secret"); + String secret_secret = PropertiesReader.get("secret_secret");*/ + + @Value("${express.key}") + private String key; + + @Value("${express.customer}") + private String customer; + String msg=""; @Autowired IExpressService expressService; diff --git a/box-bps/src/main/resources/account.properties b/box-bps/src/main/resources/account.properties index c7f7dc6a0..eca321a27 100644 --- a/box-bps/src/main/resources/account.properties +++ b/box-bps/src/main/resources/account.properties @@ -1,9 +1,9 @@ #快递100的基础账号信息,可以在这里获取 # https://poll.kuaidi100.com/manager/page/myinfo/enterprise -key = Jydbrxsm2311 -customer = 2DD48B3469B82F2B7700569093AB792B -secret = 8781ed9b35a7438499eb02fee915915a -userid = 2a62da2192c24d17a943ff78ee64f8c6 +#key = kzuyKyAE3985 +#customer = 6774D6F41D773B17027EEBE5CC902C9E +#secret = 4fc7633a027c4fe1a68b68237c236d6e +#userid = bfc0389a986f45c4b36e27d9b18b7bd3 #电子面单快递公司账号信息(非必填) partnerId = @@ -20,6 +20,6 @@ secret_key = secret_secret = #是否记录快递100接口返回结果,建议记录日志或者入库,方便后期有问题双方排查(true:启用 false: 关闭 ) -log.return.record = true +#log.return.record = true #日志记录位置,建议根据自身情况配置 -logPath = logs \ No newline at end of file +#logPath = logs \ No newline at end of file diff --git a/box-test/src/main/java/com/ruoyi/test/conrtroller/WechatApiController.java b/box-test/src/main/java/com/ruoyi/test/conrtroller/WechatApiController.java index 7439ebbbf..ef71ebbee 100644 --- a/box-test/src/main/java/com/ruoyi/test/conrtroller/WechatApiController.java +++ b/box-test/src/main/java/com/ruoyi/test/conrtroller/WechatApiController.java @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; @@ -32,7 +31,8 @@ public class WechatApiController extends BaseController { } @GetMapping("anon/userInfo") - public Map getJSON(HttpServletRequest request, HttpServletResponse response) throws IOException { + @ResponseBody + public Object getJSON(HttpServletRequest request, HttpServletResponse response) throws IOException { BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8")); StringBuilder responseStrBuilder = new StringBuilder(); @@ -40,7 +40,8 @@ public class WechatApiController extends BaseController { while ((inputStr = streamReader.readLine()) != null) { responseStrBuilder.append(inputStr); } - return JSON.parseObject(responseStrBuilder.toString(), Map.class); + //return JSON.parseObject(responseStrBuilder.toString(), Map.class); + return JSON.parse(responseStrBuilder.toString()); } diff --git a/box-test/src/main/java/com/ruoyi/test/conrtroller/XmlWebserviceController.java b/box-test/src/main/java/com/ruoyi/test/conrtroller/XmlWebserviceController.java new file mode 100644 index 000000000..5efb3a233 --- /dev/null +++ b/box-test/src/main/java/com/ruoyi/test/conrtroller/XmlWebserviceController.java @@ -0,0 +1,28 @@ +package com.ruoyi.test.conrtroller; + +import com.ruoyi.common.utils.XmlUtils; +import com.ruoyi.common.utils.http.HttpUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController + +public class XmlWebserviceController { + //private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + @PostMapping("/anon/sendXml") + public String SendXml() { + Map map = new HashMap<>(); + map.put("responseInfo", "此处为测试消息"); + String param = XmlUtils.GetTopgpRequestXml("express_testRequest", map); + String url = "http://192.168.2.81:85/web/ws/r/aws_ttsrv2_toptest"; + String returnXml = HttpUtils.sendXmlPost(url,param); + return XmlUtils.GetStatusFromTopgpResponse(returnXml).toString(); + + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index 7cd0e251d..5ee51536b 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -1,22 +1,37 @@ package com.ruoyi.web.controller.system; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.utils.http.HttpUtils; +import com.ruoyi.framework.jwt.service.IJwtTokenService; import com.ruoyi.framework.shiro.util.CustToken; import com.ruoyi.system.service.IWechatApiService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.enums.UserStatus; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.jwt.utils.JwtUtils; +import com.ruoyi.framework.shiro.service.SysPasswordService; +import com.ruoyi.system.service.ISysUserService; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.Map; /** @@ -24,9 +39,13 @@ import java.util.Map; * * @author ruoyi */ +@Api(tags = "生成AccessToken接口") @Controller public class SysLoginController extends BaseController { + @Autowired + private IJwtTokenService jwtTokenService; + @Autowired private IWechatApiService wechatApiService; @@ -83,6 +102,26 @@ public class SysLoginController extends BaseController } } + @ApiOperation("获取Json格式AccessToken") + @ApiImplicitParams({ + @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class), + }) + @PostMapping("/jwt/login") + @ResponseBody + public AjaxResult jwtLogin(String username, String password) + { + return jwtTokenService.AjaxResultJwtToken(username,password); + } + + @ApiOperation("获取String格式AccessToken") + @PostMapping("/jwt/topgplogin") + @ResponseBody + public String topgpJwtLogin(String username, String password) + { + return JSONObject.toJSONString(jwtTokenService.AjaxResultJwtToken(username,password)); + } + @GetMapping("/unauth") public String unauth() { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java index 0cfbfbadb..0a3f38239 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java @@ -55,9 +55,9 @@ public class SwaggerConfig // 用ApiInfoBuilder进行定制 return new ApiInfoBuilder() // 设置标题 - .title("标题:若依管理系统_接口文档") + .title("BPS管理系统_接口文档") // 描述 - .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") + .description("描述:用于管理系统的各类接口的文档说明。") // 作者信息 .contact(new Contact(RuoYiConfig.getName(), null, null)) // 版本 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 3ccd384ad..7ec588bd5 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -144,7 +144,27 @@ swagger: #企业微信 wechat: corpId: ww4ed3771457e5f463 - agentId: 1000080 - secret: drtHKYabI9_EgjJQ8aqDPTQkY1WUYeWUTMkYw7D_z64 + agentId: 1000082 + secret: PqTYlveYQc54T13QS-cDyuAesDaGgyMSgpZLXBNJ-Uc token: 111 - aesKey: 111 \ No newline at end of file + aesKey: 111 + +#快递100 +express: + #快递100的基础账号信息,可以在这里获取 + # https://poll.kuaidi100.com/manager/page/myinfo/enterprise + key: kzuyKyAE3985 + customer: 6774D6F41D773B17027EEBE5CC902C9E + secret: 4fc7633a027c4fe1a68b68237c236d6e + userid: bfc0389a986f45c4b36e27d9b18b7bd3 + #电子面单快递公司账号信息(非必填) + partnerId: + partnerKey: + net: + siid: + #短信模板id(非必填) + tid: + #云平台相关(非必填) + #登录云平台 https://cloud.kuaidi100.com/buyer/user/info + secret_key: + secret_secret: \ No newline at end of file diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index edd31141d..bf5675cd1 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -101,6 +101,13 @@ javax.servlet-api + + org.json + json + 20160810 + compile + + \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java index a5a190cdd..f09cbadf9 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java @@ -1,13 +1,15 @@ package com.ruoyi.common.utils; -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import com.ruoyi.common.core.text.Convert; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import com.ruoyi.common.core.text.Convert; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.BufferedReader; +import java.io.IOException; /** * 客户端工具类 @@ -161,4 +163,22 @@ public class ServletUtils } return flag; } + + /** + * 从HttpServletRequest中获取post的json对象数据content-type=“text/plain” + * @param request + * @return content + * @throws IOException + */ + public static String getRequestContent(HttpServletRequest request) throws IOException { + BufferedReader reader = request.getReader(); + char[] buf = new char[request.getContentLength()]; + int len = 0; + StringBuffer contentBuffer = new StringBuffer(); + while ((len = reader.read(buf)) != -1) { + contentBuffer.append(buf, 0, len); + } + String content= contentBuffer.toString(); + return content; + } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/XmlUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/XmlUtils.java new file mode 100644 index 000000000..2278c008c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/XmlUtils.java @@ -0,0 +1,73 @@ +package com.ruoyi.common.utils; + +import com.ruoyi.common.utils.http.HttpUtils; +import org.json.JSONObject; +import org.json.XML; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +public class XmlUtils { + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 组合TOPGP所需的XML格式 + * @param tip 调用TOPGP的Webservice的方法名 如:express_testRequest + * @param mapInfo XML中Filed对应的键值对Map + * @return xml字符串 + */ + public static String GetTopgpRequestXml(String tip, Map mapInfo){ + log.info("=======生成xml======"); + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " <Request>\n" + + " <Access>\n" + + " <Authentication user='topgui' password='' />\n" + + " <Connection application='bps' source='www.bpsemi.com' />\n" + + " <Organization name='SYSTEM' />\n" + + " <Locale language='zh_cn' />\n" + + " </Access>\n" + + " <RequestContent>\n" + + " <Parameter>\n" + + " <Record>\n" + + " <Field name="); + for(String key:mapInfo.keySet()){ + stringBuffer.append("'"+key+"' value='" +mapInfo.get(key).toString().replaceAll("&","&")+"' />\n"); + } + stringBuffer.append(" </Record>\n" + + " </Parameter>\n" + + " <Document/>\n" + + " </RequestContent>\n" + + " </Request>\n" + + " \n" + + " \n" + + " \n" + + ""); + log.info("=======生成xml结束======"); + return stringBuffer.toString(); + } + + /** + * 将TOPGP返回的XML转化为Json,并提出返回Status + * @param TopgpResonseXml 调用TOPGP的Webservice的方法名 如:express_testRequest + * @return Status JsonObject + */ + public static JSONObject GetStatusFromTopgpResponse(String TopgpResonseXml) { + JSONObject jsonObject = XML.toJSONObject(TopgpResonseXml); + + JSONObject envelope = jsonObject.getJSONObject("SOAP-ENV:Envelope"); + JSONObject body = envelope.getJSONObject("SOAP-ENV:Body"); + JSONObject express_testResponse = body.getJSONObject("fjs1:express_testResponse"); + JSONObject fjs1Response = express_testResponse.getJSONObject("fjs1:response"); + JSONObject response = fjs1Response.getJSONObject("Response"); + JSONObject execution = response.getJSONObject("Execution"); + return execution.getJSONObject("Status"); + } + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java index 11c8404b7..dcaa8c5a2 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java @@ -1,10 +1,14 @@ package com.ruoyi.common.utils.http; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintWriter; +import com.ruoyi.common.constant.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.*; +import java.io.*; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.URL; @@ -12,18 +16,6 @@ import java.net.URLConnection; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.constant.Constants; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; /** * 通用http发送方法 @@ -265,12 +257,72 @@ public class HttpUtils } } + /** + * 向指定 URL 发送xml POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + *Author yangbo + */ + public static String sendXmlPost(String url, String param) { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + String urlNameString = url; + log.info("sendPost - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8"); //发送xml需加上此请求头 + conn.addRequestProperty("SOAPAction", "\"\""); //向topgp发送xml必须加上该Name=“SOAPAction", Value="\"\"" ,否则会报415错误,不能识别XML. + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString().replace("<","<").replace(">",">"); + } + + /** * 向指定 Restful接口 发送POST方法的请求 * * @param url 发送请求的 URL * @param params 请求参数,请求参数为json的形式。例:params="{\"params\":{\"pagesize\":1000}}" * @return 返回Map, Key="statusCode",接口访问返回状态, key="result":接口返回接果 + * + * author yangbo */ //public static Map sendPostWithRest(String url, String params){ //如果参数为String类型,推送企业微信消息会乱码,因此改为Object类型,直接推送Map --yangbo 20210729 diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 4541aa3b1..0a05c2a56 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -77,12 +77,19 @@ ruoyi-system - + org.springframework.boot spring-boot-starter-data-ldap + + + com.auth0 + java-jwt + 3.4.0 + + \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java index 422654aa2..b2c10506f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java @@ -25,6 +25,8 @@ import com.ruoyi.common.constant.Constants; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.security.CipherUtils; import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.framework.jwt.auth.AllowAllCredentialsMatcher; +import com.ruoyi.framework.jwt.filter.JwtFilter; import com.ruoyi.framework.shiro.realm.UserRealm; import com.ruoyi.framework.shiro.session.OnlineSessionDAO; import com.ruoyi.framework.shiro.session.OnlineSessionFactory; @@ -177,6 +179,7 @@ public class ShiroConfig UserRealm userRealm = new UserRealm(); userRealm.setAuthorizationCacheName(Constants.SYS_AUTH_CACHE); userRealm.setCacheManager(cacheManager); + userRealm.setCredentialsMatcher(new AllowAllCredentialsMatcher()); return userRealm; } @@ -287,6 +290,8 @@ public class ShiroConfig filterChainDefinitionMap.put("/logout", "logout"); // 不需要拦截的访问 filterChainDefinitionMap.put("/login", "anon,captchaValidate"); + filterChainDefinitionMap.put("/jwt/login", "anon"); + filterChainDefinitionMap.put("/jwt/topgplogin", "anon"); // 注册相关 filterChainDefinitionMap.put("/register", "anon,captchaValidate"); // 系统权限列表 @@ -297,10 +302,14 @@ public class ShiroConfig filters.put("syncOnlineSession", syncOnlineSessionFilter()); filters.put("captchaValidate", captchaValidateFilter()); filters.put("kickout", kickoutSessionFilter()); + filters.put("jwt", new JwtFilter()); // 注销成功,则跳转到指定页面 filters.put("logout", logoutFilter()); shiroFilterFactoryBean.setFilters(filters); + // jwt 请求单独验证 + filterChainDefinitionMap.put("/api/**", "jwt"); + // 所有请求需要认证 filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/AllowAllCredentialsMatcher.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/AllowAllCredentialsMatcher.java new file mode 100644 index 000000000..9131fdcfe --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/AllowAllCredentialsMatcher.java @@ -0,0 +1,19 @@ +package com.ruoyi.framework.jwt.auth; + +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; + +/** + * 无需验证密码 + * + * @author ruoyi + */ +public class AllowAllCredentialsMatcher extends SimpleCredentialsMatcher +{ + @Override + public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) + { + return true; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/JwtToken.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/JwtToken.java new file mode 100644 index 000000000..3dfc19eac --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/auth/JwtToken.java @@ -0,0 +1,45 @@ +package com.ruoyi.framework.jwt.auth; + +import org.apache.shiro.authc.UsernamePasswordToken; + +/** + * 自定义登录Token + * + * @author ruoyi + */ +public class JwtToken extends UsernamePasswordToken +{ + private static final long serialVersionUID = 1L; + + private String token; + + public JwtToken() + { + } + + public JwtToken(String username, String password, boolean rememberMe) + { + super(username, password, rememberMe); + } + + public JwtToken(String username, String password) + { + super(username, password, false); + } + + public JwtToken(String token) + { + super("", "", false); + this.token = token; + } + + public String getToken() + { + return token; + } + + public void setToken(String token) + { + this.token = token; + } +} \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/filter/JwtFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/filter/JwtFilter.java new file mode 100644 index 000000000..980a8ae4f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/filter/JwtFilter.java @@ -0,0 +1,135 @@ +package com.ruoyi.framework.jwt.filter; + +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.web.filter.AccessControlFilter; +import org.apache.shiro.web.util.WebUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestMethod; +import com.alibaba.fastjson.JSON; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.jwt.auth.JwtToken; + +/** + * jwt 自定义拦截器 + * + * @author ruoyi + */ +public class JwtFilter extends AccessControlFilter +{ + private static final Logger LOGGER = LoggerFactory.getLogger(JwtFilter.class); + + private static final String AUTHZ_HEADER = "token"; + + private final ThreadLocal MSG_HOLDER = new ThreadLocal<>(); + + @Override + public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception + { + return super.onPreHandle(request, response, mappedValue); + } + + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception + { + return this.executeLogin(request, response); + } + + /** + * 执行登录方法(UserRealm判断,异常返回false) + */ + protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception + { + String token = WebUtils.toHttp(request).getHeader(AUTHZ_HEADER); + if (StringUtils.isEmpty(token)) + { + MSG_HOLDER.set("消息头不正确,header需要携带token参数"); + return false; + } + try + { + // 断是否有权限 + JwtToken jwtToken = new JwtToken(token); + this.getSubject(request, response).login(jwtToken); + return true; + } + catch (AuthenticationException e) + { + if (e.getCause() instanceof TokenExpiredException) + { + MSG_HOLDER.set("token已过期"); + } + else if (e.getCause() instanceof JWTVerificationException) + { + MSG_HOLDER.set("用户密码错误"); + } + else + { + MSG_HOLDER.set("用户信息验证失败:" + e.getMessage()); + } + return false; + } + } + + /** + * 请求前处理,处理跨域 + */ + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception + { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); + httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE"); + httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); + // 跨域时,option请求直接返回正常状态 + if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) + { + httpServletResponse.setStatus(HttpStatus.OK.value()); + return false; + } + return super.preHandle(request, response); + } + + /** + * 异常处理 + */ + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception + { + this.jwtFail(request, response, 401, "对不起,您无权限进行操作!"); + return false; + } + + /** + * 认证失败,异常返回 + */ + protected void jwtFail(ServletRequest request, ServletResponse response, int code, String message) + { + HttpServletResponse httpResponse = WebUtils.toHttp(response); + String contentType = "application/json;charset=UTF-8"; + httpResponse.setStatus(401); + httpResponse.setContentType(contentType); + try + { + String msg = StringUtils.isNotEmpty(MSG_HOLDER.get()) ? MSG_HOLDER.get() : message; + AjaxResult ajaxResult = new AjaxResult().put(AjaxResult.CODE_TAG, code).put(AjaxResult.MSG_TAG, msg); + PrintWriter printWriter = httpResponse.getWriter(); + printWriter.append(JSON.toJSONString(ajaxResult)); + } + catch (IOException e) + { + LOGGER.error("sendChallenge error,can not resolve httpServletResponse"); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/IJwtTokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/IJwtTokenService.java new file mode 100644 index 000000000..79c383efa --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/IJwtTokenService.java @@ -0,0 +1,13 @@ +package com.ruoyi.framework.jwt.service; + +import com.ruoyi.common.core.domain.AjaxResult; + +public interface IJwtTokenService { + /** + * 获取AjaxResult格式的jwt token + * @param username 用户名 + * @param password 密码 + * @return jwtToken + */ + public AjaxResult AjaxResultJwtToken(String username, String password); +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/impl/JwtTokenServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/impl/JwtTokenServiceImpl.java new file mode 100644 index 000000000..65e6649b6 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/service/impl/JwtTokenServiceImpl.java @@ -0,0 +1,59 @@ +package com.ruoyi.framework.jwt.service.impl; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.enums.UserStatus; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.jwt.service.IJwtTokenService; +import com.ruoyi.framework.jwt.utils.JwtUtils; +import com.ruoyi.framework.shiro.service.SysPasswordService; +import com.ruoyi.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JwtTokenServiceImpl implements IJwtTokenService { + @Autowired + private ISysUserService userService; + + @Autowired + private SysPasswordService passwordService; + /** + * 获取AjaxResult格式的jwt token + * + * @param username 用户名 + * @param password 密码 + * @return jwtToken + */ + @Override + public AjaxResult AjaxResultJwtToken(String username, String password) { + if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) + { + return AjaxResult.error("账号和密码不能为空!"); + } + + SysUser user = userService.selectUserByLoginName(username); + if (user == null) + { + return AjaxResult.error("用户不存在/密码错误!"); + } + + if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + return AjaxResult.error("对不起,您的账号已被删除!"); + } + + if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + return AjaxResult.error("用户已封禁,请联系管理员!"); + } + + if (!passwordService.matches(user, password)) + { + return AjaxResult.error("用户不存在/密码错误!"); + } + + String token = JwtUtils.createToken(username, user.getPassword()); + return AjaxResult.success("登录成功,请妥善保管您的token信息").put("token", token); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/utils/JwtUtils.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/utils/JwtUtils.java new file mode 100644 index 000000000..c0ce30121 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/jwt/utils/JwtUtils.java @@ -0,0 +1,66 @@ +package com.ruoyi.framework.jwt.utils; + +import java.util.Date; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.interfaces.DecodedJWT; + +/** + * jwt 工具类 + * + * @author ruoyi + */ +public class JwtUtils +{ + private static final long EXPIRE_TIME = 30 * 60 * 1000; + + private static final String CLAIM_NAME = "username"; + + public static String createToken(String username, String password) + { + return createToken(username, password, EXPIRE_TIME); + } + + public static String createToken(String username, String password, long expireTime) + { + Date date = new Date(System.currentTimeMillis() + expireTime); + // 加密处理密码 + Algorithm algorithm = Algorithm.HMAC256(password); + return JWT.create().withClaim(CLAIM_NAME, username).withExpiresAt(date).sign(algorithm); + } + + public static void verify(String username, String dbPwd, String token) + { + Algorithm algorithm = Algorithm.HMAC256(dbPwd); + JWTVerifier jwtVerifier = JWT.require(algorithm).withClaim(CLAIM_NAME, username).build(); + try + { + jwtVerifier.verify(token); + } + catch (TokenExpiredException e) + { + throw new TokenExpiredException("token已过期"); + } + catch (JWTVerificationException e) + { + throw new JWTVerificationException("token验证失败"); + } + } + + public static String getUserName(String token) + { + try + { + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim(CLAIM_NAME).asString(); + } + catch (JWTDecodeException e) + { + return null; + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java index 88ad4d249..5723523a0 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java @@ -4,6 +4,7 @@ import java.util.HashSet; import java.util.Set; import com.ruoyi.framework.shiro.util.CustToken; +import org.apache.shiro.authc.AccountException; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; @@ -23,16 +24,21 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.RoleBlockedException; import com.ruoyi.common.exception.user.UserBlockedException; +import com.ruoyi.common.exception.user.UserDeleteException; import com.ruoyi.common.exception.user.UserNotExistsException; import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; import com.ruoyi.common.utils.ShiroUtils; +import com.ruoyi.framework.jwt.auth.JwtToken; +import com.ruoyi.framework.jwt.utils.JwtUtils; import com.ruoyi.framework.shiro.service.SysLoginService; import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; /** * 自定义Realm 处理登录 权限 @@ -52,6 +58,9 @@ public class UserRealm extends AuthorizingRealm @Autowired private SysLoginService loginService; + @Autowired + private ISysUserService userService; + /** * 授权 */ @@ -86,55 +95,96 @@ public class UserRealm extends AuthorizingRealm * 登录认证 */ @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) + throws AuthenticationException { - //UsernamePasswordToken upToken = (UsernamePasswordToken) token; - CustToken upToken= (CustToken) token; - String loginType = upToken.getLoginType(); - String username = upToken.getUsername(); - String password = ""; + if (authenticationToken instanceof JwtToken) + { + JwtToken jwtToken = (JwtToken) authenticationToken; + String token = jwtToken.getToken(); + String username = JwtUtils.getUserName(token); + if (username == null) + { + throw new AccountException("token 验证失败"); + } + SysUser user = userService.selectUserByLoginName(username); + if (user == null) + { + throw new AuthenticationException("用户数据不存在"); + } - if (upToken.getPassword() != null) - { - password = new String(upToken.getPassword()); - } + try + { + JwtUtils.verify(username, user.getPassword(), jwtToken.getToken()); - SysUser user = null; - try - { - user = loginService.login(username, password,loginType); + if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + throw new UserDeleteException(); + } + + if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + throw new UserBlockedException(); + } + } + catch (Exception e) + { + log.info("对用户[" + username + "]进行jwt登录验证..验证未通过{}", e.getMessage()); + throw new AuthenticationException(e.getMessage(), e); + } + + return new SimpleAuthenticationInfo(user, null, getName()); } - catch (CaptchaException e) + else { - throw new AuthenticationException(e.getMessage(), e); + //UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken; + CustToken upToken= (CustToken) authenticationToken; + String loginType = upToken.getLoginType(); + String username = upToken.getUsername(); + String password = ""; + + if (upToken.getPassword() != null) + { + password = new String(upToken.getPassword()); + } + + SysUser user = null; + try + { + user = loginService.login(username, password,loginType); + } + catch (CaptchaException e) + { + throw new AuthenticationException(e.getMessage(), e); + } + catch (UserNotExistsException e) + { + throw new UnknownAccountException(e.getMessage(), e); + } + catch (UserPasswordNotMatchException e) + { + throw new IncorrectCredentialsException(e.getMessage(), e); + } + catch (UserPasswordRetryLimitExceedException e) + { + throw new ExcessiveAttemptsException(e.getMessage(), e); + } + catch (UserBlockedException e) + { + throw new LockedAccountException(e.getMessage(), e); + } + catch (RoleBlockedException e) + { + throw new LockedAccountException(e.getMessage(), e); + } + catch (Exception e) + { + log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage()); + throw new AuthenticationException(e.getMessage(), e); + } + SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); + return info; } - catch (UserNotExistsException e) - { - throw new UnknownAccountException(e.getMessage(), e); - } - catch (UserPasswordNotMatchException e) - { - throw new IncorrectCredentialsException(e.getMessage(), e); - } - catch (UserPasswordRetryLimitExceedException e) - { - throw new ExcessiveAttemptsException(e.getMessage(), e); - } - catch (UserBlockedException e) - { - throw new LockedAccountException(e.getMessage(), e); - } - catch (RoleBlockedException e) - { - throw new LockedAccountException(e.getMessage(), e); - } - catch (Exception e) - { - log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage()); - throw new AuthenticationException(e.getMessage(), e); - } - SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); - return info; } /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java index d9812d8a4..21a9c876d 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -13,6 +13,7 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.exception.BusinessException; import com.ruoyi.common.exception.DemoModeException; import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.security.PermissionUtils; /** @@ -32,7 +33,7 @@ public class GlobalExceptionHandler public Object handleAuthorizationException(HttpServletRequest request, AuthorizationException e) { log.error(e.getMessage(), e); - if (ServletUtils.isAjaxRequest(request)) + if (ServletUtils.isAjaxRequest(request) || StringUtils.isNotEmpty(request.getHeader("token"))) { return AjaxResult.error(PermissionUtils.getMsg(e.getMessage())); }