From efbed347c8b659ca13207a1dbe34e77fdb003949 Mon Sep 17 00:00:00 2001 From: XiaoRuby <3114200645@qq.com> Date: 星期五, 07 七月 2023 16:40:32 +0800 Subject: [PATCH] LIMS管理系统框架-开发-1.0.0 --- user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java | 15 user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java | 28 + user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java | 170 ++++++++++ user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java | 55 +++ user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java | 167 ++++++++++ user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java | 39 +- user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java | 15 user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java | 28 + pom.xml | 8 user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java | 34 ++ /dev/null | 5 framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java | 16 user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java | 12 user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java | 61 +++ user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java | 48 ++ user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java | 17 user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java | 57 +++ user-server/pom.xml | 6 user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java | 160 ++++++++++ user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java | 3 20 files changed, 893 insertions(+), 51 deletions(-) diff --git a/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java b/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java index 560b57f..64012d1 100644 --- a/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java +++ b/framework/src/main/java/com/yuanchu/limslaboratory/config/WebMvcConfig.java @@ -1,23 +1,27 @@ package com.yuanchu.limslaboratory.config; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.io.File; +import java.util.List; @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { - // swagger鍙鍖栭厤缃� - registry.addResourceHandler("/systemPictures/**") - .addResourceLocations("file:" + System.getProperty("user.dir")+ File.separator+"uploadFile"+File.separator+"systemPictures"+File.separator); - registry.addResourceHandler("/uploadFile/pluginFiles/logo/**") - .addResourceLocations("file:" + System.getProperty("user.dir")+ File.separator+"uploadFile"+File.separator+"pluginFiles"+File.separator+"logo"+File.separator); - + //閰嶇疆鎷︽埅鍣ㄨ闂潤鎬佽祫婧� registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); //璁剧疆鏂囦欢铏氭嫙璺緞鏄犲皠 diff --git a/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java b/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java deleted file mode 100644 index 34eaa8e..0000000 --- a/framework/src/main/java/com/yuanchu/limslaboratory/utils/JwtUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.yuanchu.limslaboratory.utils; - - -import com.auth0.jwt.JWT; -import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTCreationException; - -import java.util.Date; - -public class JwtUtils { - // 杩囨湡鏃堕棿 2 灏忔椂 -// private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000; - - private static final long EXPIRE_TIME = 10; - /** - * 鐢熸垚绛惧悕,鍑嗙‘鍦拌鏄敓鎴恡oken - * @param secret - * @return - */ - public static String sign(String account, String secret){ - try{ - Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); - Algorithm algorithm = Algorithm.HMAC256(secret); - //闄勫甫username,nickname淇℃伅 - return JWT.create() - .withClaim("account",account) - .withExpiresAt(date) - .sign(algorithm); - } catch (JWTCreationException e){ - e.printStackTrace(); - return null; - } catch (Exception e){ - e.printStackTrace(); - return null; - } - } -} diff --git a/pom.xml b/pom.xml index 6622ba9..580ba65 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,7 @@ <mybatis-plus.version>3.4.0</mybatis-plus.version> <openfeign.version>3.1.3</openfeign.version> <feign-okhttp.version>11.0</feign-okhttp.version> + <shiro.version>1.5.3</shiro.version> </properties> <dependencies> @@ -127,6 +128,13 @@ <artifactId>feign-okhttp</artifactId> <version>${feign-okhttp.version}</version> </dependency> + + <!--瀹夊叏妗嗘灦shiro--> + <dependency> + <groupId>org.apache.shiro</groupId> + <artifactId>shiro-spring-boot-starter</artifactId> + <version>${shiro.version}</version> + </dependency> </dependencies> </dependencyManagement> diff --git a/user-server/pom.xml b/user-server/pom.xml index c0fd1c3..96c60be 100644 --- a/user-server/pom.xml +++ b/user-server/pom.xml @@ -43,6 +43,12 @@ <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> + + <!--瀹夊叏妗嗘灦shiro--> + <dependency> + <groupId>org.apache.shiro</groupId> + <artifactId>shiro-spring-boot-starter</artifactId> + </dependency> </dependencies> </project> diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java b/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java index 04dc927..b54743d 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/clients/UserLoginUtils.java @@ -1,5 +1,8 @@ package com.yuanchu.limslaboratory.clients; +import com.yuanchu.limslaboratory.pojo.User; +import com.yuanchu.limslaboratory.shiro.utils.JwtUtils; +import com.yuanchu.limslaboratory.utils.RedisUtil; import com.yuanchu.limslaboratory.vo.Result; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -19,6 +22,7 @@ @Value("${login.secret}") private String LoginSecret; + // public Result<Map<String, Object>> LoginExamine(User user){ // Map<String, Object> mapData = new HashMap<>(); // mapData.put("LoginUserID", LoginUserID); @@ -30,7 +34,7 @@ // Map data = (Map) result.getData(); // String token = data.get("token").toString(); // data.remove("token"); -// user.setMap(data); +//// user.setMap(data); // //瀛樺叆redis,浜屼釜灏忔椂鍚庡垹闄� // RedisUtil.set(token, user, 2); // // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔� @@ -48,26 +52,17 @@ // } // } - public Result<Map<String, Object>> LoginExamine(){ - Map<String, Object> mapData = new HashMap<>(); - mapData.put("LoginUserID", LoginUserID); - mapData.put("LoginSecret", LoginSecret); - Result<?> code = userClient.BusynessUserLogin(mapData); - if (code.getCode() == 200){ - Result<?> result = userClient.BusynessUserLoginToken(code.getData().toString()); - if (result.getCode() == 200){ - Map data = (Map) result.getData(); - String token = data.get("token").toString(); - data.remove("token"); - // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔� - HashMap<String, Object> map = new HashMap<>(); - map.put("token", token); - return Result.success(map); - } else { - return Result.fail(result.getMessage()); - } - } else { - return Result.fail(code.getMessage()); - } + + public Result<Map<String, Object>> LoginExamine(User user){ + String token = JwtUtils.sign(user.getAccount()); + //瀛樺叆redis,浜屼釜灏忔椂鍚庡垹闄� + RedisUtil.set(token, user, 2); + // 灏嗙鍙戠殑 JWT token 杩斿洖缁欏墠绔� + HashMap<String, Object> map = new HashMap<>(); + String refresh = JwtUtils.sign(user.getAccount()); + map.put("token", token); + map.put("refresh", refresh); + RedisUtil.set(user.getAccount(), map, 120); + return Result.success(map); } } diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java b/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java index 5bb5aca..b2eaf01 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/controller/UserController.java @@ -1,6 +1,20 @@ package com.yuanchu.limslaboratory.controller; - +import com.yuanchu.limslaboratory.clients.UserLoginUtils; +import com.yuanchu.limslaboratory.pojo.User; +import com.yuanchu.limslaboratory.shiro.realm.ShiroRealm; +import com.yuanchu.limslaboratory.utils.SpringUtils; +import com.yuanchu.limslaboratory.vo.Result; +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.IncorrectCredentialsException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.subject.Subject; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -15,6 +29,38 @@ */ @RestController @RequestMapping("/user") +@Api(tags = "鐢ㄦ埛妯″潡") public class UserController { + @ApiOperation("鐢ㄦ埛鐧诲綍") + @ApiImplicitParams(value = { + @ApiImplicitParam(name = "account", value = "璐﹀彿", dataTypeClass = String.class, required = true), + @ApiImplicitParam(name = "password", value = "瀵嗙爜", dataTypeClass = String.class, required = true) + }) + @PostMapping("/login") + public Result<?> UserLogin(String account, String password){ + boolean loginSuccess = false; + Subject subject = SecurityUtils.getSubject(); + if (!subject.isAuthenticated()) { + UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(account, password); + try { + subject.login(usernamePasswordToken); + loginSuccess = true; + } catch (UnknownAccountException e) { + return Result.fail(202, "娌℃湁鎵惧埌璇ヨ处鍙凤紝璇锋鏌ヨ緭鍏ワ紒"); + } catch (IncorrectCredentialsException e) { + return Result.fail(202, "瀵嗙爜涓嶅尮閰嶏紝璇锋鏌ヨ緭鍏ワ紒"); + } + } + if (loginSuccess) { + // 鑾峰彇shiroRealm涓殑鏁版嵁 + ShiroRealm bean = SpringUtils.getBean(ShiroRealm.class); + User user = bean.user; + user.setPassword(null); + UserLoginUtils bean1 = SpringUtils.getBean(UserLoginUtils.class); + return bean1.LoginExamine(user); + }else { + return Result.fail("鐧诲綍澶辫触"); + } + } } diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java index 175ba92..d3508b0 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Enterprise.java @@ -1,9 +1,14 @@ package com.yuanchu.limslaboratory.pojo; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +16,7 @@ /** * <p> - * + * * </p> * * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃 @@ -46,11 +51,13 @@ @ApiModelProperty(value = "鑱旂郴浜虹數璇�") private String linkPhone; - @ApiModelProperty(value = "鍒涘缓鏃堕棿") - private LocalDateTime createTime; + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date createTime; - @ApiModelProperty(value = "鏇存柊鏃堕棿") - private LocalDateTime updateTime; + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date updateTime; @ApiModelProperty(value = "閿�") private Integer version; diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java index d1ed711..2950361 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/EnterpriseUserList.java @@ -1,9 +1,14 @@ package com.yuanchu.limslaboratory.pojo; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +16,7 @@ /** * <p> - * + * * </p> * * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃 @@ -37,9 +42,13 @@ @ApiModelProperty(value = "0:鍒犻櫎;1:姝e父") private Integer state; - private LocalDateTime createTime; + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date createTime; - private LocalDateTime updateTime; + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date updateTime; private Integer version; diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java index 152fe60..cf2e20c 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/Role.java @@ -1,9 +1,14 @@ package com.yuanchu.limslaboratory.pojo; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +16,7 @@ /** * <p> - * + * * </p> * * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃 @@ -37,9 +42,13 @@ @ApiModelProperty(value = "閫昏緫鍒犻櫎 姝e父>=1,鍒犻櫎<=0") private Integer state; - private LocalDateTime createTime; + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date createTime; - private LocalDateTime updateTime; + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date updateTime; @ApiModelProperty(value = "涔愯閿�") private Integer version; diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java index 34f3d2f..9ae5655 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/pojo/User.java @@ -1,17 +1,25 @@ package com.yuanchu.limslaboratory.pojo; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; + import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; +import net.sf.jsqlparser.expression.DateTimeLiteralExpression; /** * <p> - * + * * </p> * * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃 @@ -46,12 +54,20 @@ @ApiModelProperty(value = "骞撮緞") private Integer age; + @TableLogic(value = "1", delval = "0") @ApiModelProperty(value = "鍦ㄨ亴鐘舵�� 姝e父>=1,绂昏亴<=0") private Integer jobState; - private LocalDateTime createTime; + @ApiModelProperty(value = "涓�х鍚�") + private String info; - private LocalDateTime updateTime; + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8") + private Date updateTime; private Integer version; diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java b/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java index ff42a44..674166d 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/service/UserService.java @@ -3,6 +3,8 @@ import com.yuanchu.limslaboratory.pojo.User; import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; + /** * <p> * 鏈嶅姟绫� @@ -13,4 +15,5 @@ */ public interface UserService extends IService<User> { + User AccordingUsernameSelectAll(String account); } diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java b/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java index 6cf6e1f..beb4cea 100644 --- a/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/service/impl/UserServiceImpl.java @@ -1,10 +1,13 @@ package com.yuanchu.limslaboratory.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.yuanchu.limslaboratory.pojo.User; import com.yuanchu.limslaboratory.mapper.UserMapper; import com.yuanchu.limslaboratory.service.UserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; + +import javax.annotation.Resource; /** * <p> @@ -17,4 +20,13 @@ @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { + @Resource + private UserMapper mapper; + + @Override + public User AccordingUsernameSelectAll(String account) { + LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(User::getAccount, account); + return mapper.selectOne(wrapper); + } } diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java new file mode 100644 index 0000000..e4872db --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/JwtToken.java @@ -0,0 +1,28 @@ +package com.yuanchu.limslaboratory.shiro; + +import com.yuanchu.limslaboratory.shiro.utils.JwtUtils; +import org.apache.shiro.authc.AuthenticationToken; + +public class JwtToken implements AuthenticationToken { + private static final long serialVersionUID = 1L; + + // 鍔犲瘑鍚庣殑 JWT token涓� + private String token; + + private String account; + + public JwtToken(String token) { + this.token = token; + this.account = JwtUtils.getClaimFiled(token, "account"); + } + + @Override + public Object getPrincipal() { + return this.account; + } + + @Override + public Object getCredentials() { + return token; + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java new file mode 100644 index 0000000..4110709 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/MultiRealmAuthenticator.java @@ -0,0 +1,61 @@ +package com.yuanchu.limslaboratory.shiro; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.pam.AuthenticationStrategy; +import org.apache.shiro.authc.pam.ModularRealmAuthenticator; +import org.apache.shiro.realm.Realm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; + +public class MultiRealmAuthenticator extends ModularRealmAuthenticator { + private static final Logger log = LoggerFactory.getLogger(MultiRealmAuthenticator.class); + + @Override + protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) + throws AuthenticationException { + AuthenticationStrategy strategy = getAuthenticationStrategy(); + + AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token); + + if (log.isTraceEnabled()) { + log.trace("Iterating through {} realms for PAM authentication", realms.size()); + } + AuthenticationException authenticationException = null; + for (Realm realm : realms) { + + aggregate = strategy.beforeAttempt(realm, token, aggregate); + + if (realm.supports(token)) { + + log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm); + + AuthenticationInfo info = null; + try { + info = realm.getAuthenticationInfo(token); + } catch (AuthenticationException e) { + authenticationException = e; + if (log.isDebugEnabled()) { + String msg = "Realm [" + realm + + "] threw an exception during a multi-realm authentication attempt:"; + log.debug(msg, e); + } + } + + aggregate = strategy.afterAttempt(realm, token, info, aggregate, authenticationException); + + } else { + log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token); + } + } + if (authenticationException != null) { + throw authenticationException; + } + aggregate = strategy.afterAllAttempts(token, aggregate); + + return aggregate; + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java new file mode 100644 index 0000000..be5d706 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/config/ShiroConfig.java @@ -0,0 +1,167 @@ +package com.yuanchu.limslaboratory.shiro.config; + +import com.yuanchu.limslaboratory.shiro.filter.JwtFilter; +import com.yuanchu.limslaboratory.shiro.MultiRealmAuthenticator; +import com.yuanchu.limslaboratory.shiro.realm.JwtRealm; +import com.yuanchu.limslaboratory.shiro.realm.ShiroRealm; +import com.yuanchu.limslaboratory.shiro.utils.JwtCredentialsMatcher; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.authc.pam.AuthenticationStrategy; +import org.apache.shiro.authc.pam.FirstSuccessfulStrategy; +import org.apache.shiro.authc.pam.ModularRealmAuthenticator; +import org.apache.shiro.authz.Authorizer; +import org.apache.shiro.authz.ModularRealmAuthorizer; +import org.apache.shiro.crypto.hash.Md5Hash; +import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; +import org.apache.shiro.mgt.DefaultSubjectDAO; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.mgt.SessionStorageEvaluator; +import org.apache.shiro.realm.Realm; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import java.util.*; + +@Configuration +public class ShiroConfig { + + /** + * 涓嶅悜 Spring瀹瑰櫒涓敞鍐� JwtFilter Bean锛岄槻姝� Spring 灏� JwtFilter 娉ㄥ唽涓哄叏灞�杩囨护鍣� + * 鍏ㄥ眬杩囨护鍣ㄤ細瀵规墍鏈夎姹傝繘琛屾嫤鎴紝鑰屾湰渚嬩腑鍙渶瑕佹嫤鎴櫎 /login 鍜� /logout 澶栫殑璇锋眰 + * 鍙︿竴绉嶇畝鍗曞仛娉曟槸锛氱洿鎺ュ幓鎺� jwtFilter()涓婄殑 @Bean 娉ㄨВ + */ + @Bean + public FilterRegistrationBean<Filter> registration(JwtFilter filter) { + FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>(filter); + registration.setEnabled(false); + return registration; + } + + //ShiroFilter杩囨护鎵�鏈夎姹� + @Bean + public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) { + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + //缁橲hiroFilter閰嶇疆瀹夊叏绠$悊鍣� + shiroFilterFactoryBean.setSecurityManager(securityManager); + + // 娣诲姞 jwt 涓撶敤杩囨护鍣紝鎷︽埅闄� /login 鍜� /logout 澶栫殑璇锋眰 + Map<String, Filter> filterMap = new LinkedHashMap<>(); + filterMap.put("jwtFilter", new JwtFilter()); + shiroFilterFactoryBean.setFilters(filterMap); + + //閰嶇疆绯荤粺鍏叡璧勬簮 + Map<String, String> map = new HashMap<String, String>(); + + // swagger鏀捐 + map.put("/doc.html", "anon"); + map.put("/webjars/**/**", "anon"); + map.put("/swagger-resources", "anon"); + map.put("/api-docs", "anon"); + map.put("/v3/**", "anon"); + + + map.put("/user/login/**","anon");//琛ㄧず杩欎釜涓哄叕鍏辫祫婧� 涓�瀹氭槸鍦ㄥ彈闄愯祫婧愪笂闈� +// map.put("/**","jwtFilter");//琛ㄧず杩欎釜璧勬簮闇�瑕佽璇佸拰鎺堟潈 + + shiroFilterFactoryBean.setFilterChainDefinitionMap(map); + + return shiroFilterFactoryBean; + } + + /** + * 閰嶇疆 ModularRealmAuthenticator + */ + @Bean + public ModularRealmAuthenticator authenticator() { + ModularRealmAuthenticator authenticator = new MultiRealmAuthenticator(); + // 璁剧疆澶� Realm鐨勮璇佺瓥鐣ワ紝榛樿 AtLeastOneSuccessfulStrategy + AuthenticationStrategy strategy = new FirstSuccessfulStrategy(); + authenticator.setAuthenticationStrategy(strategy); + return authenticator; + } + + + /** + * 绂佺敤session, 涓嶄繚瀛樼敤鎴风櫥褰曠姸鎬併�備繚璇佹瘡娆¤姹傞兘閲嶆柊璁よ瘉 + */ + @Bean + protected SessionStorageEvaluator sessionStorageEvaluator() { + DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator(); + sessionStorageEvaluator.setSessionStorageEnabled(false); + return sessionStorageEvaluator; + } + + /** + * 閰嶇疆 SecurityManager锛氭潈闄愮鐞嗗櫒 + */ + @Bean + public DefaultWebSecurityManager securityManager() { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + + // 1.韬唤楠岃瘉鍣� + securityManager.setAuthenticator(authenticator()); + + // 2.绠$悊Realm + List<Realm> realms = new ArrayList<Realm>(16); + realms.add(JwtRealm()); + realms.add(shiroRealm()); + securityManager.setRealms(realms); // 閰嶇疆澶氫釜realm + + // 3.鍏抽棴shiro鑷甫鐨剆ession + DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); + subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator()); + securityManager.setSubjectDAO(subjectDAO); + + return securityManager; + } + +// 鍒涘缓鑷畾涔塕ealm + @Bean + public Realm shiroRealm() { + return new ShiroRealm(); + } + + @Bean + public Realm JwtRealm(){ + return new JwtRealm(); + } + + + // 浠ヤ笅涓変腑bean閫氱敤锛屽浐瀹氶厤缃� + + /** + * 浜ょ敱 Spring 鏉ヨ嚜鍔ㄥ湴绠$悊 Shiro-Bean 鐨勭敓鍛藉懆鏈� + */ + @Bean + public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + /** + * 涓� Spring-Bean 寮�鍚 Shiro 娉ㄨВ鐨勬敮鎸� + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + + /** + * 寮�鍚疉OP鏂规硶绾ф潈闄愭鏌� + */ + @Bean + public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { + DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); + advisorAutoProxyCreator.setProxyTargetClass(true); + return advisorAutoProxyCreator; + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java new file mode 100644 index 0000000..a03022e --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/filter/JwtFilter.java @@ -0,0 +1,170 @@ +package com.yuanchu.limslaboratory.shiro.filter; + +import com.yuanchu.limslaboratory.shiro.JwtToken; +import com.yuanchu.limslaboratory.shiro.utils.JwtUtils; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; +import org.apache.shiro.web.util.WebUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; + +@Component +public class JwtFilter extends BasicHttpAuthenticationFilter { + private Logger log = LoggerFactory.getLogger(this.getClass()); + + public Integer code; + public String message; + + /** + * 鍓嶇疆澶勭悊 + */ + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { + HttpServletRequest httpServletRequest = WebUtils.toHttp(request); + HttpServletResponse httpServletResponse = WebUtils.toHttp(response); + // 璺ㄥ煙鏃朵細棣栧厛鍙戦�佷竴涓猳ption璇锋眰锛岃繖閲屾垜浠粰option璇锋眰鐩存帴杩斿洖姝e父鐘舵�� + if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { + httpServletResponse.setStatus(HttpStatus.OK.value()); + return false; + } + return super.preHandle(request, response); + } + + /** + * 鍚庣疆澶勭悊 + */ + @Override + protected void postHandle(ServletRequest request, ServletResponse response) { + // 娣诲姞璺ㄥ煙鏀寔 + this.fillCorsHeader(WebUtils.toHttp(request), WebUtils.toHttp(response)); + } + + /** + * 杩囨护鍣ㄦ嫤鎴姹傜殑鍏ュ彛鏂规硶 + * 杩斿洖 true 鍒欏厑璁歌闂� + * 杩斿洖false 鍒欑姝㈣闂紝浼氳繘鍏� onAccessDenied() + */ + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { + // 濡傛灉token涓虹┖涓嶈閫氳繃 + String header = ((HttpServletRequest) request).getHeader(JwtUtils.AUTH_HEADER); + if (ObjectUtils.isEmpty(header)){ + code = 503; + message = "STS token瑙g爜杩囩▼涓紝鐢变簬鍐呴儴璋冪敤澶辫触瀵艰嚧瑙g爜澶辫触锛岃绋嶅悗鍐嶈瘯銆�"; + return false; + } + boolean allowed = false; + try { + // 妫�娴婬eader閲岀殑 JWT token鍐呭鏄惁姝g‘锛屽皾璇曚娇鐢� token杩涜鐧诲綍 + allowed = executeLogin(request, response); + } catch (IllegalStateException e) { // not found any token + log.error("Not found any token"); + } catch (Exception e) { + log.error("Error occurs when login", e); + } + return allowed || super.isPermissive(mappedValue); + } + + + /** + * 韬唤楠岃瘉,妫�鏌� JWT token 鏄惁鍚堟硶 + */ + @Override + protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { + AuthenticationToken token = createToken(request, response); + if (token == null) { + String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " + + "must be created in order to execute a login attempt."; + throw new IllegalStateException(msg); + } + + try { + Subject subject = getSubject(request, response); + subject.login(token); // 浜ょ粰 Shiro 鍘昏繘琛岀櫥褰曢獙璇� + return onLoginSuccess(token, subject, request, response); + } catch (AuthenticationException e) { + return onLoginFailure(token, e, request, response); + } + } + + /** + * 浠� Header 閲屾彁鍙� JWT token + */ + @Override + protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + String authorization = httpServletRequest.getHeader(JwtUtils.AUTH_HEADER); + JwtToken token = new JwtToken(authorization); + return token; + } + + /** + * isAccessAllowed()鏂规硶杩斿洖false锛屼細杩涘叆璇ユ柟娉曪紝琛ㄧず鎷掔粷璁块棶 + */ + @Override + protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { + HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse); + httpResponse.setCharacterEncoding("UTF-8"); + httpResponse.setContentType("application/json;charset=UTF-8"); + httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); + PrintWriter writer = httpResponse.getWriter(); + writer.write("{\"errCode\": "+ code +", \"msg\": \"" + message +"\"}"); + fillCorsHeader(WebUtils.toHttp(servletRequest), httpResponse); + return false; + } + + /** + * Shiro 鍒╃敤 JWT token 鐧诲綍鎴愬姛锛屼細杩涘叆璇ユ柟娉� + */ + @Override + protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, + ServletResponse response) { + HttpServletResponse httpResponse = WebUtils.toHttp(response); + String newToken = null; + if (token instanceof JwtToken) { + newToken = JwtUtils.refreshTokenExpired(token.getCredentials().toString(), JwtUtils.SECRET); + } + if (newToken != null) + httpResponse.setHeader(JwtUtils.AUTH_HEADER, newToken); + return true; + } + + /** + * Shiro 鍒╃敤 JWT token 鐧诲綍澶辫触锛屼細杩涘叆璇ユ柟娉� + */ + @Override + protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, + ServletResponse response) { + // 姝ゅ鐩存帴杩斿洖 false 锛屼氦缁欏悗闈㈢殑 onAccessDenied()鏂规硶杩涜澶勭悊 + String error = e.getClass().toString().split("\\.")[4]; + if (error.equals("IncorrectCredentialsException")) { + code = 10010; + } else { + code = 401; + } + message = e.getMessage(); + return false; + } + + /** + * 娣诲姞璺ㄥ煙鏀寔 + */ + protected void fillCorsHeader(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { + httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); + httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,HEAD"); + httpServletResponse.setHeader("Access-Control-Allow-Headers", + httpServletRequest.getHeader("Access-Control-Request-Headers")); + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java new file mode 100644 index 0000000..4293742 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/JwtRealm.java @@ -0,0 +1,57 @@ +package com.yuanchu.limslaboratory.shiro.realm; + +import com.yuanchu.limslaboratory.pojo.User; +import com.yuanchu.limslaboratory.shiro.JwtToken; +import com.yuanchu.limslaboratory.shiro.utils.JwtCredentialsMatcher; +import com.yuanchu.limslaboratory.utils.RedisUtil; +import org.apache.shiro.authc.*; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; + +public class JwtRealm extends AuthorizingRealm { + /** + * 闄愬畾杩欎釜 Realm 鍙鐞嗘垜浠嚜瀹氫箟鐨� JwtToken + */ + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof JwtToken; + } + + /** + * 姝ゅ鐨� SimpleAuthenticationInfo 鍙繑鍥炰换鎰忓�硷紝瀵嗙爜鏍¢獙鏃朵笉浼氱敤鍒板畠 + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { + JwtToken jwtToken = (JwtToken) authcToken; + if (jwtToken.getPrincipal() == null) { + throw new AccountException("Token鍙傛暟寮傚父锛�"); + } + // 褰撳墠鐢ㄦ埛 + String account = jwtToken.getPrincipal().toString(); + // 褰撳墠鐢ㄦ埛鐨則oken + String credentials = (String)jwtToken.getCredentials(); + User user = (User) RedisUtil.get(credentials); + // 鐢ㄦ埛涓嶅瓨鍦� + if (user == null) { + throw new UnknownAccountException("鐢ㄦ埛涓嶅瓨鍦紒"); + } + SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, account, getName()); + return info; + } + + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + return info; + } + + @Override + public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { + // 璁剧疆鍔犲瘑绠楁硶 + CredentialsMatcher jwtCredentialsMatcher = new JwtCredentialsMatcher(); + super.setCredentialsMatcher(jwtCredentialsMatcher); + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java new file mode 100644 index 0000000..ec429f4 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/realm/ShiroRealm.java @@ -0,0 +1,55 @@ +package com.yuanchu.limslaboratory.shiro.realm; + +import com.yuanchu.limslaboratory.pojo.User; +import com.yuanchu.limslaboratory.service.UserService; +import com.yuanchu.limslaboratory.utils.MyUtils; +import com.yuanchu.limslaboratory.utils.SpringUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.springframework.util.ObjectUtils; + +public class ShiroRealm extends AuthorizingRealm { + + public User user; + + /** + * 闄愬畾杩欎釜 Realm 鍙鐞� UsernamePasswordToken + */ + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof UsernamePasswordToken; + } + + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { + return null; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) { + String principal = (String) authenticationToken.getPrincipal(); + //鑾峰彇UserService瀵硅薄 + UserService userService = SpringUtils.getBean(UserService.class); + user = userService.AccordingUsernameSelectAll(principal); + MyUtils.PrintLog(user.toString()); + if (!ObjectUtils.isEmpty(user)) { + return new SimpleAuthenticationInfo(user.getAccount(), user.getPassword(), this.getName()); + } else { + throw new UnknownAccountException(); + } + } + + @Override + public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { +// HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); +// //璁剧疆浣跨敤MD5鍔犲瘑绠楁硶 +// hashedCredentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME); +// //鏁e垪娆℃暟 +// hashedCredentialsMatcher.setHashIterations(1024); +// super.setCredentialsMatcher(hashedCredentialsMatcher); + super.setCredentialsMatcher(credentialsMatcher); + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java new file mode 100644 index 0000000..a04c5b6 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtCredentialsMatcher.java @@ -0,0 +1,34 @@ +package com.yuanchu.limslaboratory.shiro.utils; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.springframework.stereotype.Component; + +@Component +public class JwtCredentialsMatcher implements CredentialsMatcher { + /** + * JwtCredentialsMatcher鍙渶楠岃瘉JwtToken鍐呭鏄惁鍚堟硶 + */ + @Override + public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) { + + String token = authenticationToken.getCredentials().toString(); + String account = authenticationToken.getPrincipal().toString(); + try { + Algorithm algorithm = Algorithm.HMAC256(JwtUtils.getSecret()); + JWTVerifier verifier = JWT.require(algorithm).withClaim("account", account).build(); + verifier.verify(token); + return true; + } catch (JWTVerificationException e) { + + } catch (Exception e){ + e.printStackTrace(); + } + return false; + } +} diff --git a/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java new file mode 100644 index 0000000..f2cd618 --- /dev/null +++ b/user-server/src/main/java/com/yuanchu/limslaboratory/shiro/utils/JwtUtils.java @@ -0,0 +1,160 @@ +package com.yuanchu.limslaboratory.shiro.utils; + + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import javax.annotation.PostConstruct; +import java.io.UnsupportedEncodingException; +import java.util.Calendar; +import java.util.Date; +import java.util.Map; + +@Component +public class JwtUtils { + private static String staticSecret; + + @Value("${login.secret}") + private String secret; + + @PostConstruct + public void getApiToken() { + staticSecret = this.secret; + } + + public static String getSecret() { + // lockie.zou + return staticSecret; + } + + // 杩囨湡鏃堕棿 2 灏忔椂 + private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000; + //鑷繁瀹氬埗瀵嗛挜 + public static final String SECRET = "J-(t]Poe9P"; + + //璇锋眰澶� + public static final String AUTH_HEADER = "X-Token"; // X-Authorization-With + + /** + * 楠岃瘉token鏄惁姝g‘ + * @param token + * @return + */ + public static boolean verify(String token){ + try{ + String account = getClaimFiled(token, "account"); + if (account == null){ + return false; + } + Algorithm algorithm = Algorithm.HMAC256(getSecret()); + JWTVerifier verifier = JWT.require(algorithm).withClaim("account",account).build(); + verifier.verify(token); + return true; + } catch (JWTVerificationException exception){ + return false; + } catch (Exception e){ + e.printStackTrace(); + return false; + } + } + + /** + * 鑾峰緱token涓殑鑷畾涔変俊鎭�,涓�鑸槸鑾峰彇token鐨剈sername锛屾棤闇�secret瑙e瘑涔熻兘鑾峰緱 + * @param token + * @param filed + * @return + */ + public static String getClaimFiled(String token, String filed){ + try{ + if (!ObjectUtils.isEmpty(token)){ + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim(filed).asString(); + } + return null; + } catch (JWTDecodeException e){ + return null; + } + } + + /** + * 鐢熸垚绛惧悕,鍑嗙‘鍦拌鏄敓鎴恡oken + * @return + */ + public static String sign(String account){ + try{ + Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); + Algorithm algorithm = Algorithm.HMAC256(SECRET); + //闄勫甫username,nickname淇℃伅 + return JWT.create() + .withClaim("account",account) + .withExpiresAt(date) + .sign(algorithm); + } catch (JWTCreationException e){ + e.printStackTrace(); + return null; + } catch (Exception e){ + e.printStackTrace(); + return null; + } + } + + /** + * 鑾峰彇token鐨勭鍙戞椂闂� + * @param token + * @return + */ + public static Date getIssueAt(String token){ + try{ + DecodedJWT jwt = JWT.decode(token); + return jwt.getIssuedAt(); + } catch (JWTDecodeException e){ + e.printStackTrace(); + return null; + } + } + + /** + * 楠岃瘉token鏄惁杩囨湡 + * @param token + * @return + */ + public static boolean isTokenExpired(String token){ + Date now = Calendar.getInstance().getTime(); + DecodedJWT jwt = JWT.decode(token); + return jwt.getExpiresAt().before(now); + } + + /** + * 鍒锋柊token鐨勬湁鏁堟湡 + * @param token + * @param secret + * @return + */ + public static String refreshTokenExpired(String token, String secret){ + DecodedJWT jwt = JWT.decode(token); //瑙f瀽token + Map<String, Claim> claims = jwt.getClaims(); //鑾峰彇token鐨勫弬鏁颁俊鎭� + + try{ + Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); + Algorithm algorithm = Algorithm.HMAC256(secret); + JWTCreator.Builder builder = JWT.create().withExpiresAt(date); + for(Map.Entry<String,Claim> entry : claims.entrySet()){ + builder.withClaim(entry.getKey(),entry.getValue().asString()); + } + return builder.sign(algorithm); + } catch (JWTCreationException e){ + e.printStackTrace(); + return null; + } + } +} diff --git a/user-server/src/main/resources/mapper/AdminMapper.xml b/user-server/src/main/resources/mapper/AdminMapper.xml deleted file mode 100644 index cfa44cb..0000000 --- a/user-server/src/main/resources/mapper/AdminMapper.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> -<mapper namespace="com.yuanchu.limslaboratory.mapper.AdminMapper"> - -</mapper> -- Gitblit v1.9.3