cnas-require/src/main/java/com/ruoyi/require/controller/DeviceController.java
@@ -160,7 +160,7 @@ } @ApiOperation(value = "éè¿é¡¹ç®è·å设å¤å表") @PostMapping("/selectDeviceByCategory") @GetMapping("/selectDeviceByCategory") public Result selectDeviceByCategory(String inspectionItem, String inspectionItemSubclass,String sonLaboratory) { return Result.success(deviceService.selectDeviceByCategory(inspectionItem, inspectionItemSubclass,sonLaboratory)); } @@ -192,7 +192,7 @@ @ApiOperation(value = "å¤æè¯¥è®¾å¤æ¯å¦å¯ä»¥æ°é") @GetMapping("/determineWhetherToCollectData") public Result<?> determineWhetherToCollectData(@RequestParam("managementNumber") String managementNumber, HttpServletRequest request) { public Result<?> determineWhetherToCollectData(String managementNumber, HttpServletRequest request) { return deviceService.determineWhetherToCollectData(managementNumber, request); } inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderPlanController.java
@@ -102,8 +102,8 @@ @ApiOperation(value = "äº¤æ¥æé®") @PostMapping("/upPlanUser") public Result<?> upPlanUser(Integer userId, Integer orderId, String sonLaboratory) { return Result.success(insOrderPlanService.upPlanUser(userId, orderId, sonLaboratory)); public Result<?> upPlanUser(@RequestBody UpInsOrderDTO upInsOrderDTO) { return Result.success(insOrderPlanService.upPlanUser(upInsOrderDTO.getUserId(), upInsOrderDTO.getOrderId(), upInsOrderDTO.getSonLaboratory())); } @ApiOperation(value = "å¤æäº¤æ¥çè¯éªå®¤") @@ -142,18 +142,18 @@ } /** * @param param 模æ¿å 容 * @param currentTable å½å模æ¿id * @param sampleId å½åæ ·åid * @param orderId å½å订åid * @param sonLaboratory åè¯éªå®¤ * @param inspectionOrderDTO æ£éªæ°æ® * @return */ @ApiOperation(value = "ä¿åæ£éªå 容") @PostMapping("/saveInsContext") public Result<?> saveInsContext(String param, Integer currentTable, Integer sampleId, Integer orderId, String sonLaboratory,Boolean isDelete) { Map<String, Object> param2 = JSON.parseObject(param, Map.class); insOrderPlanService.saveInsContext(param2, currentTable, sampleId, orderId, sonLaboratory,isDelete); public Result<?> saveInsContext(@RequestBody InspectionOrderDTO inspectionOrderDTO) { insOrderPlanService.saveInsContext(inspectionOrderDTO.getParam(), inspectionOrderDTO.getCurrentTable(), inspectionOrderDTO.getSampleId(), inspectionOrderDTO.getOrderId(), inspectionOrderDTO.getSonLaboratory(), inspectionOrderDTO.getIsDelete()); return Result.success(); } inspect-server/src/main/java/com/ruoyi/inspect/dto/InspectionOrderDTO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,51 @@ package com.ruoyi.inspect.dto; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.util.Map; /** * æ£éªä¿åæ°æ®ä¼ è¾å¯¹è±¡dto */ @Data public class InspectionOrderDTO implements Serializable { /** * æ£éªåæ° */ @ApiModelProperty("æ£éªåæ°") private Map<String, Object> param; /** * å½å模æ¿id */ @ApiModelProperty("å½å模æ¿id") private Integer currentTable; /** * æ ·åid */ @ApiModelProperty("æ ·åid") private Integer sampleId; /** * 订åid */ @ApiModelProperty("订åid") private Integer orderId; /** * åå®éªå®¤ */ @ApiModelProperty("åå®éªå®¤") private String sonLaboratory; /** * æ¯å¦å é¤ */ @ApiModelProperty("æ¯å¦å é¤") private Boolean isDelete; } inspect-server/src/main/java/com/ruoyi/inspect/dto/UpInsOrderDTO.java
@@ -24,4 +24,7 @@ @ApiModelProperty(value = "åè¯éªå®¤") private String sonLaboratory; @ApiModelProperty("交æ¥äººåid") private Integer userId; } inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsSampleMapper.java
@@ -49,13 +49,13 @@ List<SampleProductDto3> selectSampleProductListByOrderId3(@Param("ids") List<Integer> ids); List<SampleProductDto> getInsOrderAndSample(Integer id, String laboratory); List<SampleProductDto> getInsOrderAndSample(@Param("id")Integer id, @Param("laboratory")String laboratory); String getSampleEn(String sample); List<InsProduct> getInsProduct1(Integer id, String laboratory); List<InsProduct> getInsProduct1(@Param("id") Integer id, @Param("laboratory") String laboratory); List<InsProduct> getInsProduct5(Integer id, String laboratory); List<InsProduct> getInsProduct5(@Param("id") Integer id, @Param("laboratory") String laboratory); List<InsProduct> getInsProduct2(@Param("id") Integer id, @Param("sonLaboratory") String sonLaboratory); notice-server/src/main/java/com/ruoyi/notice/controller/InformationNotificationController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,81 @@ package com.ruoyi.notice.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.Result; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.notice.pojo.InformationNotification; import com.ruoyi.notice.service.InformationNotificationService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Map; /** * <p> * æ¶æ¯éç¥ å端æ§å¶å¨ * </p> * * @author æ±èéµ·éç½ç»ç§ææéå ¬å¸ * @since 2024-04-23 02:14:30 */ @Api(tags = "æ¶æ¯éç¥") @RestController @RequestMapping("/informationNotification") public class InformationNotificationController { @Autowired private InformationNotificationService informationNotificationService; @ApiOperation(value = "æ¶æ¯éç¥-æ»å¨å页æ¥è¯¢") @GetMapping("page") public Result<?> getPage(Long size, Long current, String messageType) { return Result.success(informationNotificationService.getPage(new Page<>(current, size), messageType)); } @ApiOperation(value = "æ¶æ¯éç¥-æ´æ°æ¶æ¯ç¶æï¼æç»ãæ¥æ¶ï¼") @PutMapping("updateMessageStatus") @Log(title = "æ¶æ¯éç¥", businessType = BusinessType.UPDATE) public Result<?> updateMessageStatus(@RequestBody InformationNotification informationNotification) { informationNotificationService.updateById(informationNotification); return Result.success(); } @ApiOperation(value = "æ¶æ¯éç¥-æ è®°ææä¿¡æ¯ä¸ºå·²è¯»/å 餿æå·²è¯»æ¶æ¯") @PutMapping("informationReadOrDelete/{isMarkAllInformationRead}") public Result<?> markAllInformationReadOrDeleteAllReadMessages(@PathVariable("isMarkAllInformationRead") Boolean isMarkAllInformationRead) { informationNotificationService.markAllInformationReadOrDeleteAllReadMessages(isMarkAllInformationRead); return Result.success(); } @ApiOperation(value = "æ¶æ¯éç¥-å 餿°æ®") @DeleteMapping("deleteDataBasedOnId") @Log(title = "æ¶æ¯éç¥", businessType = BusinessType.DELETE) public Result<?> deleteDataBasedOnId(Integer id) { informationNotificationService.removeById(id); return Result.success(); } @ApiOperation(value = "æ¶æ¯éç¥-æ¥è¯¢æ¯å¦å卿ªè¯»æ°æ®") @GetMapping("checkForUnreadData") public Result<?> checkForUnreadData() { return Result.success(informationNotificationService.checkForUnreadData()); } @ApiOperation(value = "æ¶æ¯éç¥-ç¹å»è¯¦æ 触åä¿®æ¹ç¶æä¸ºå·²è¯»") @PutMapping("triggerModificationStatusToRead/{id}") @Log(title = "æ¶æ¯éç¥", businessType = BusinessType.UPDATE) public Result<?> triggerModificationStatusToRead(@PathVariable("id") Integer id) { informationNotificationService.triggerModificationStatusToRead(id); return Result.success(); } @ApiOperation(value = "æ¶æ¯éç¥-è·åé¦é¡µåç§æ¶æ¯æ°é") @GetMapping("getNumberFourTypesMessagesHomePage") public Result<?> getNumberFourTypesMessagesHomePage() { Map<String, Object> data = informationNotificationService.getNumberFourTypesMessagesHomePage(); return Result.success(data); } } notice-server/src/main/java/com/ruoyi/notice/mapper/InformationNotificationMapper.java
@@ -6,6 +6,7 @@ import com.ruoyi.notice.dto.InformationNotificationDto; import com.ruoyi.notice.pojo.InformationNotification; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> @@ -18,5 +19,5 @@ @Mapper public interface InformationNotificationMapper extends BaseMapper<InformationNotification> { IPage<InformationNotificationDto> getPage(Page page, String messageType, Integer userId); IPage<InformationNotificationDto> getPage(Page page, @Param("messageType") String messageType, @Param("userId")Integer userId); } ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
@@ -67,6 +67,16 @@ } /** * æ ¹æ®åå ¸åç§°æ¥è¯¢åå ¸æ°æ® */ @PreAuthorize("@ss.hasPermi('system:dict:query')") @GetMapping(value = "/selectDictDataByName/{dictName}") public AjaxResult selectDictDataByName(@PathVariable String dictName) { return success(dictTypeService.selectDictDataByName(dictName)); } /** * æ°å¢åå ¸ç±»å */ @PreAuthorize("@ss.hasPermi('system:dict:add')") ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -2,7 +2,9 @@ import java.util.List; import java.util.Set; import java.util.UUID; import com.ruoyi.common.config.SsoBean; import com.ruoyi.common.core.vo.SysUserVO; import com.ruoyi.system.mapper.UserMapper; import org.springframework.beans.factory.annotation.Autowired; @@ -44,6 +46,9 @@ @Autowired private UserMapper userMapper; @Autowired private SsoBean ssoBean; /** * ç»å½æ¹æ³ @@ -103,4 +108,34 @@ List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId); return AjaxResult.success(menuService.buildMenus(menus)); } /** * è·åç»ä¸ç»å½å¹³å°è·åCODEå°å * * @return */ @GetMapping("/getSsoAuthUrl") public AjaxResult getSsoAuthUrl() { String uuid = UUID.randomUUID().toString(); return AjaxResult.success("æä½æå", ssoBean.getUrl() + "/oauth2/auth?response_type=code&scope=openid&client_id=" + ssoBean.getClientId() + "&redirect_uri=" + ssoBean.getCallbackUrl() + "&state=" + uuid); } /** * åç¹ç»å½ * * @param code ç»å½ä¿¡æ¯ * @return ç»æ */ @PostMapping("/loginBySSO") public AjaxResult loginBySSO(String code) { AjaxResult ajax = AjaxResult.success(); // çæä»¤ç String token = loginService.loginBySSO(code); ajax.put(Constants.TOKEN, token); return ajax; } } ruoyi-admin/src/main/resources/application.yml
@@ -36,6 +36,7 @@ level: com.ruoyi: debug org.springframework: warn com.deepoove: off #å ³époi-tlæ¥å¿ # ç¨æ·é ç½® user: @@ -47,6 +48,11 @@ # Springé ç½® spring: jackson: # å ¨å±æ¶é´å¤ç LocalDateTimeæ¶é´åºåå· date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 serialization: write-dates-as-timestamps: false #rabbitmqé ç½® rabbitmq: host: 127.0.0.1 @@ -145,3 +151,9 @@ cache-enabled: false log-impl: # org.apache.ibatis.logging.stdout.StdOutImpl #éå¢ç»ä¸ç»å½ sso: url: https://ztt-sso.asuncloud.net clientId: 47ded514-f447-43b4-afdf-181c10e2222d clientSecret: ea93d26a68863da5d71a6e3355ec22df callbackUrl: https://ztzb-lims.ztt.cn/thirdpartylogin ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -1,38 +1,41 @@ #éè¯¯æ¶æ¯ not.null=* å¿ é¡»å¡«å user.jcaptcha.error=éªè¯ç é误 user.jcaptcha.expire=éªè¯ç 已失æ user.not.exists=ç¨æ·ä¸åå¨/å¯ç é误 user.password.not.match=ç¨æ·ä¸åå¨/å¯ç é误 user.password.retry.limit.count=å¯ç è¾å ¥é误{0}次 user.password.retry.limit.exceed=å¯ç è¾å ¥é误{0}次ï¼å¸æ·éå®{1}åé user.password.delete=对ä¸èµ·ï¼æ¨çè´¦å·å·²è¢«å é¤ user.blocked=ç¨æ·å·²å°ç¦ï¼è¯·è系管çå role.blocked=è§è²å·²å°ç¦ï¼è¯·è系管çå login.blocked=å¾éæ¾ï¼è®¿é®IP已被åå ¥ç³»ç»é»åå user.logout.success=éåºæå #\u9519\u8BEF\u6D88\u606F not.null=* \u5FC5\u987B\u586B\u5199 user.jcaptcha.error=\u9A8C\u8BC1\u7801\u9519\u8BEF user.jcaptcha.expire=\u9A8C\u8BC1\u7801\u5DF2\u5931\u6548 user.not.exists=\u7528\u6237\u4E0D\u5B58\u5728/\u5BC6\u7801\u9519\u8BEF user.password.not.match=\u7528\u6237\u4E0D\u5B58\u5728/\u5BC6\u7801\u9519\u8BEF user.sso.not.match=\u5355\u70B9\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25 user.password.retry.limit.count=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21 user.password.retry.limit.exceed=\u5BC6\u7801\u8F93\u5165\u9519\u8BEF{0}\u6B21\uFF0C\u5E10\u6237\u9501\u5B9A{1}\u5206\u949F user.password.delete=\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u7684\u8D26\u53F7\u5DF2\u88AB\u5220\u9664 user.blocked=\u7528\u6237\u5DF2\u5C01\u7981\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 role.blocked=\u89D2\u8272\u5DF2\u5C01\u7981\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 login.blocked=\u5F88\u9057\u61BE\uFF0C\u8BBF\u95EEIP\u5DF2\u88AB\u5217\u5165\u7CFB\u7EDF\u9ED1\u540D\u5355 user.logout.success=\u9000\u51FA\u6210\u529F user.sso.logout.success=\u5355\u70B9\u767B\u5F55\u9000\u51FA\u6210\u529F length.not.valid=é¿åº¦å¿ é¡»å¨{min}å°{max}个å符ä¹é´ length.not.valid=\u957F\u5EA6\u5FC5\u987B\u5728{min}\u5230{max}\u4E2A\u5B57\u7B26\u4E4B\u95F4 user.username.not.valid=* 2å°20个æ±åãåæ¯ãæ°åæä¸åçº¿ç»æï¼ä¸å¿ 须以鿰åå¼å¤´ user.password.not.valid=* 5-50个å符 user.email.not.valid=é®ç®±æ ¼å¼é误 user.mobile.phone.number.not.valid=ææºå·æ ¼å¼é误 user.login.success=ç»å½æå user.register.success=注åæå user.notfound=è¯·éæ°ç»å½ user.forcelogout=管çå强å¶éåºï¼è¯·éæ°ç»å½ user.unknown.error=æªç¥é误ï¼è¯·éæ°ç»å½ user.username.not.valid=* 2\u523020\u4E2A\u6C49\u5B57\u3001\u5B57\u6BCD\u3001\u6570\u5B57\u6216\u4E0B\u5212\u7EBF\u7EC4\u6210\uFF0C\u4E14\u5FC5\u987B\u4EE5\u975E\u6570\u5B57\u5F00\u5934 user.password.not.valid=* 5-50\u4E2A\u5B57\u7B26 ##æä»¶ä¸ä¼ æ¶æ¯ upload.exceed.maxSize=ä¸ä¼ çæä»¶å¤§å°è¶ åºéå¶çæä»¶å¤§å°ï¼<br/>å 许çæä»¶æå¤§å¤§å°æ¯ï¼{0}MBï¼ upload.filename.exceed.length=ä¸ä¼ çæä»¶åæé¿{0}个å符 user.email.not.valid=\u90AE\u7BB1\u683C\u5F0F\u9519\u8BEF user.mobile.phone.number.not.valid=\u624B\u673A\u53F7\u683C\u5F0F\u9519\u8BEF user.login.success=\u767B\u5F55\u6210\u529F user.sso.login.success=\u5355\u70B9\u767B\u5F55\u6210\u529F user.register.success=\u6CE8\u518C\u6210\u529F user.notfound=\u8BF7\u91CD\u65B0\u767B\u5F55 user.forcelogout=\u7BA1\u7406\u5458\u5F3A\u5236\u9000\u51FA\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55 user.unknown.error=\u672A\u77E5\u9519\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55 ##æé no.permission=æ¨æ²¡ææ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] no.create.permission=æ¨æ²¡æåå»ºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] no.update.permission=æ¨æ²¡æä¿®æ¹æ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] no.delete.permission=æ¨æ²¡æå 餿°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] no.export.permission=æ¨æ²¡æå¯¼åºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] no.view.permission=æ¨æ²¡ææ¥çæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] ##\u6587\u4EF6\u4E0A\u4F20\u6D88\u606F upload.exceed.maxSize=\u4E0A\u4F20\u7684\u6587\u4EF6\u5927\u5C0F\u8D85\u51FA\u9650\u5236\u7684\u6587\u4EF6\u5927\u5C0F\uFF01<br/>\u5141\u8BB8\u7684\u6587\u4EF6\u6700\u5927\u5927\u5C0F\u662F\uFF1A{0}MB\uFF01 upload.filename.exceed.length=\u4E0A\u4F20\u7684\u6587\u4EF6\u540D\u6700\u957F{0}\u4E2A\u5B57\u7B26 ##\u6743\u9650 no.permission=\u60A8\u6CA1\u6709\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] no.create.permission=\u60A8\u6CA1\u6709\u521B\u5EFA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] no.update.permission=\u60A8\u6CA1\u6709\u4FEE\u6539\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] no.delete.permission=\u60A8\u6CA1\u6709\u5220\u9664\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] no.export.permission=\u60A8\u6CA1\u6709\u5BFC\u51FA\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] no.view.permission=\u60A8\u6CA1\u6709\u67E5\u770B\u6570\u636E\u7684\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u6DFB\u52A0\u6743\u9650 [{0}] ruoyi-common/pom.xml
@@ -16,7 +16,11 @@ </description> <dependencies> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-common</artifactId> <version>4.1.0</version> </dependency> <!-- Springæ¡æ¶åºæ¬çæ ¸å¿å·¥å · --> <dependency> <groupId>org.springframework</groupId> ruoyi-common/src/main/java/com/ruoyi/common/config/SsoBean.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,37 @@ package com.ruoyi.common.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; /** * zhuo */ @Configuration @Component @ConfigurationProperties(prefix = "sso") @Data public class SsoBean { /** * åç¹ç»å½åºç¨id */ private String clientId; /** * åç¹ç»å½åºç¨ç§é¥ */ private String clientSecret; /** * åç¹ç»å½æå¡å°å */ private String url; /** * åç¹ç»å½åè°å°å */ private String callbackUrl; } ruoyi-common/src/main/java/com/ruoyi/common/utils/JackSonUtil.java
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.stereotype.Component; @@ -20,7 +21,7 @@ */ @Component public class JackSonUtil { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule()).disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); private static final ObjectWriter OBJECT_WRITER = OBJECT_MAPPER.writerWithDefaultPrettyPrinter(); public static void marshal(File file, Object value) throws Exception { ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -1,10 +1,13 @@ package com.ruoyi.framework.config; import com.ruoyi.framework.web.ssoAuth.SsoCodeAuthenticationProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -21,6 +24,9 @@ import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; import java.util.ArrayList; import java.util.List; /** * spring securityé ç½® * @@ -34,7 +40,14 @@ * èªå®ä¹ç¨æ·è®¤è¯é»è¾ */ @Autowired @Qualifier("UserDetailsServiceImpl") private UserDetailsService userDetailsService; /** * èªå®ä¹ç¨æ·è®¤è¯é»è¾ */ @Autowired @Qualifier("UserDetailsByOpenIdServiceImpl") private UserDetailsService userDetailsServiceByOpenId; /** * 认è¯å¤±è´¥å¤çç±» @@ -75,7 +88,16 @@ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); return new ProviderManager(daoAuthenticationProvider); // ssoç»éé´æ Provider SsoCodeAuthenticationProvider wxCodeAuthenticationProvider = new SsoCodeAuthenticationProvider(); wxCodeAuthenticationProvider.setUserDetailsService(userDetailsServiceByOpenId); List<AuthenticationProvider> providers = new ArrayList<>(); providers.add(wxCodeAuthenticationProvider); providers.add(daoAuthenticationProvider); return new ProviderManager(providers); } /** @@ -111,7 +133,7 @@ .authorizeHttpRequests((requests) -> { permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll()); // 对äºç»å½login 注åregister éªè¯ç captchaImage å 许å¿åè®¿é® requests.antMatchers("/login", "/register", "/captchaImage").permitAll() requests.antMatchers("/login", "/register", "/captchaImage","/getSsoAuthUrl","/loginBySSO").permitAll() // éæèµæºï¼å¯å¿åè®¿é® .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**", "/img/**", "/word/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() ruoyi-framework/src/main/java/com/ruoyi/framework/model/SsoOauthTokenModel.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.framework.model; import lombok.Data; /** * zhuo */ @Data public class SsoOauthTokenModel { private String access_token; private String expires_in; private String id_token; private String scope; private String token_type; } ruoyi-framework/src/main/java/com/ruoyi/framework/model/SsoUserInfoModel.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,40 @@ package com.ruoyi.framework.model; import com.alibaba.fastjson2.annotation.JSONField; import lombok.Data; /** * zhuo */ @Data public class SsoUserInfoModel { private String avatar; @JSONField(name="nick_name") private String nickName; private String openid; @JSONField(name="org_id") private String orgId; @JSONField(name="org_name") private String orgName; @JSONField(name="org_role") private String orgRole; @JSONField(name="phone_number") private String phoneNumber; private String sid; private String sub; @JSONField(name="employee_id") private String employeeId; @JSONField(name="department_code") private String departmentCode; } ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
@@ -1,14 +1,7 @@ package com.ruoyi.framework.security.handle; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import com.alibaba.fastjson2.JSON; import com.ruoyi.common.config.SsoBean; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.model.LoginUser; @@ -18,6 +11,16 @@ import com.ruoyi.framework.manager.AsyncManager; import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.web.service.TokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * èªå®ä¹éåºå¤çç±» è¿åæå @@ -29,6 +32,10 @@ { @Autowired private TokenService tokenService; @Autowired private RedisTemplate redisTemplate; @Autowired private SsoBean ssoBean; /** * éåºå¤ç @@ -40,14 +47,24 @@ throws IOException, ServletException { LoginUser loginUser = tokenService.getLoginUser(request); String loginOutUrl = null; if (StringUtils.isNotNull(loginUser)) { String userName = loginUser.getUsername(); // å é¤ç¨æ·ç¼åè®°å½ tokenService.delLoginUser(loginUser.getToken()); // è®°å½ç¨æ·éåºæ¥å¿ AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success"))); // æ¸ é¤åç¹ç»å½ä¿¡æ¯ Object idToken = redisTemplate.opsForValue().get("ssoOauthToken:idToken:" + userName); if (idToken != null) { loginOutUrl = ssoBean.getUrl() + "/oauth2/sessions/logout?id_token_hint=" + idToken; redisTemplate.delete("ssoOauthToken:idToken:" + userName); AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.sso.logout.success"))); } else { AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success"))); } } ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success")))); ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"), loginOutUrl))); } } ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -1,7 +1,29 @@ package com.ruoyi.framework.web.service; import javax.annotation.Resource; import javax.net.ssl.SSLContext; import com.alibaba.fastjson.JSON; import com.ruoyi.common.config.SsoBean; import com.ruoyi.framework.model.SsoOauthTokenModel; import com.ruoyi.framework.model.SsoUserInfoModel; import com.ruoyi.framework.web.ssoAuth.SsoCodeAuthenticationToken; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.TrustStrategy; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.apache.http.NameValuePair; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -29,11 +51,23 @@ import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysUserService; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * ç»å½æ ¡éªæ¹æ³ * * @author ruoyi */ @Slf4j @Component public class SysLoginService { @@ -47,10 +81,17 @@ private RedisCache redisCache; @Autowired private ISysUserService userService; private ISysUserService sysUserService; @Autowired private ISysConfigService configService; @Autowired private SsoBean ssoBean; @Autowired private RedisTemplate redisTemplate; /** * ç»å½éªè¯ @@ -176,6 +217,169 @@ sysUser.setUserId(userId); sysUser.setLoginIp(IpUtils.getIpAddr()); sysUser.setLoginDate(DateUtils.getNowDate()); userService.updateUserProfile(sysUser); sysUserService.updateUserProfile(sysUser); } /** * åç¹ç»å½ * @param code * @return */ public String loginBySSO(String code) { // è·ååç¹ç»å½token SsoOauthTokenModel tokenModel = this.getSsoAccessToken(code); if (tokenModel == null) { throw new RuntimeException("åç¹ç»å½éªè¯å¤±è´¥"); } // è·ååç¹ç»å½ç¨æ·ä¿¡æ¯ SsoUserInfoModel userInfo = this.getSsoUserInfo(tokenModel.getAccess_token()); if (userInfo == null) { throw new RuntimeException("åç¹ç»å½éªè¯å¤±è´¥"); } // æ¥è¯¢æ¬å°ç¨æ·ä¿¡æ¯ LoginUser loginUser = this.getSsoLoginToken(userInfo.getEmployeeId()); recordLoginInfo(loginUser.getUserId()); // å建ç»å½ä¿¡æ¯ AsyncManager.me().execute(AsyncFactory.recordLogininfor(userInfo.getEmployeeId(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.sso.login.success"))); redisTemplate.opsForValue().set("ssoOauthToken:idToken:" + userInfo.getEmployeeId(), tokenModel.getId_token(), 3, TimeUnit.DAYS); // çætoken return tokenService.createToken(loginUser); } /** * ***** è·åæ¬å°ç¨æ·ä¿¡æ¯ ***** * @param username * @return */ public LoginUser getSsoLoginToken(String username) { // ç¨æ·éªè¯ Authentication authentication = null; SysUser sysUser = sysUserService.selectUserByUserName(username); if (sysUser == null) { throw new ServiceException("å½åç³»ç»æ²¡æè¯¥ç¨æ·"); } try { // æ éå¯ç è·åç¨æ·ä¿¡æ¯ authentication = authenticationManager.authenticate(new SsoCodeAuthenticationToken(username)); } catch (Exception e) { if (e instanceof BadCredentialsException) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.sso.not.match"))); throw new UserPasswordNotMatchException(); } else { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); throw new ServiceException(e.getMessage()); } } finally { AuthenticationContextHolder.clearContext(); } AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.sso.login.success"))); return (LoginUser) authentication.getPrincipal(); } /** * **** è·ååç¹ç»å½token **** * @param code * @return */ public SsoOauthTokenModel getSsoAccessToken(String code) { List<NameValuePair> list = new LinkedList<>(); list.add(new BasicNameValuePair("grant_type", "authorization_code")); list.add(new BasicNameValuePair("code", code)); list.add(new BasicNameValuePair("client_id", ssoBean.getClientId())); list.add(new BasicNameValuePair("client_secret", ssoBean.getClientSecret())); list.add(new BasicNameValuePair("redirect_uri", ssoBean.getCallbackUrl())); Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/x-www-form-urlencoded"); headers.put("Accept", "application/json"); String result = doPost(ssoBean.getUrl() + "/oauth2/token", headers, list); if (org.apache.commons.lang3.StringUtils.isBlank(result)) { return null; } return JSON.parseObject(result, SsoOauthTokenModel.class); } /** * ***è·ååç¹ç»å½ç¨æ·ä¿¡æ¯*** * @param accessToken * @return */ public SsoUserInfoModel getSsoUserInfo(String accessToken) { Map<String, String> headers = new HashMap<>(); headers.put("Authorization", "Bearer " + accessToken); String result = doPost(ssoBean.getUrl() + "/userinfo", headers, null); if (org.apache.commons.lang3.StringUtils.isBlank(result)) { return null; } return JSON.parseObject(result, SsoUserInfoModel.class); } public static String doPost(String url, Map<String, String> headers, List<NameValuePair> params) { CloseableHttpClient client = createSSLClientDefault(); CloseableHttpResponse response = null; try { HttpPost method = new HttpPost(url); headers.forEach(method::setHeader); if (params != null) { method.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); } response = client.execute(method); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); return EntityUtils.toString(entity); } } catch (Exception e) { log.error("ç»ä¸ç»å½è¯·æ±åºç°å¼å¸¸", e.getMessage()); } finally { try { if (client != null) { client.close(); } if (response != null) { response.close(); } } catch (Exception e) { log.error("ç»ä¸ç»å½è¯·æ±åºç°å¼å¸¸", e.getMessage()); } } return null; } // // private static CloseableHttpClient createSSLClientDefault() { try { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { //ä¿¡ä»»ææ @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext); return HttpClients.custom().setSSLSocketFactory(sslsf).build(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } return HttpClients.createDefault(); } } ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ package com.ruoyi.framework.web.service; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.service.ISysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service("UserDetailsByOpenIdServiceImpl") public class UserDetailsByOpenIdServiceImpl implements UserDetailsService { @Autowired private ISysUserService userService; @Autowired private SysPermissionService permissionService; @Override public UserDetails loadUserByUsername(String openId) throws UsernameNotFoundException { SysUser user = userService.selectUserByUserName(openId); if (StringUtils.isNull(user)) { throw new UsernameNotFoundException("ç»å½ç¨æ·ï¼" + openId + " ä¸åå¨"); } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { throw new BaseException("对ä¸èµ·ï¼æ¨çè´¦å·ï¼" + openId + " 已被å é¤"); } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { throw new BaseException("对ä¸èµ·ï¼æ¨çè´¦å·ï¼" + openId + " å·²åç¨"); } // åè¥ä¾çåºå« æ¯æ²¡æéªè¯å¯ç return createLoginUser(user); } public UserDetails createLoginUser(SysUser user) { return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); } } ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java
@@ -1,12 +1,5 @@ package com.ruoyi.framework.web.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.UserStatus; @@ -14,20 +7,27 @@ import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.service.ISysUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; /** * ç¨æ·éªè¯å¤ç * * @author ruoyi */ @Service @Service("UserDetailsServiceImpl") public class UserDetailsServiceImpl implements UserDetailsService { private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); @Autowired private ISysUserService userService; @Autowired private SysPasswordService passwordService; ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,42 @@ package com.ruoyi.framework.web.ssoAuth; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; public class SsoCodeAuthenticationProvider implements AuthenticationProvider { private UserDetailsService userDetailsService; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { SsoCodeAuthenticationToken authenticationToken = (SsoCodeAuthenticationToken) authentication; String openId = (String) authenticationToken.getPrincipal(); UserDetails userDetails = userDetailsService.loadUserByUsername(openId); // æ¤æ¶é´ææååï¼åºå½éæ° new ä¸ä¸ªæ¥æé´æç authenticationResult è¿å SsoCodeAuthenticationToken authenticationResult = new SsoCodeAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } @Override public boolean supports(Class<?> authentication) { // 夿 authentication æ¯ä¸æ¯ WxCodeAuthenticationToken çåç±»æåæ¥å£ return SsoCodeAuthenticationToken.class.isAssignableFrom(authentication); } public UserDetailsService getUserDetailsService() { return userDetailsService; } public void setUserDetailsService(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } } ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,63 @@ package com.ruoyi.framework.web.ssoAuth; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.SpringSecurityCoreVersion; import java.util.Collection; public class SsoCodeAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; /** * å¨ UsernamePasswordAuthenticationToken ä¸è¯¥å段代表ç»å½çç¨æ·åï¼ * å¨è¿é就代表ç»å½çopenId */ private final Object principal; /** * æå»ºä¸ä¸ªæ²¡æé´æç SsoCodeAuthenticationToken */ public SsoCodeAuthenticationToken(Object principal) { super(null); this.principal = principal; setAuthenticated(false); } /** * æå»ºæ¥æé´æç SsoCodeAuthenticationToken */ public SsoCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; // must use super, as we override super.setAuthenticated(true); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } @Override public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { if (isAuthenticated) { throw new IllegalArgumentException( "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); } super.setAuthenticated(false); } @Override public void eraseCredentials() { super.eraseCredentials(); } }