三江统一登录更改
This commit is contained in:
parent
e204640f2e
commit
573295d316
@ -1,24 +1,28 @@
|
||||
package com.zhgd.xmgl.modules.basicdata.controller;
|
||||
|
||||
import com.gexin.fastjson.JSON;
|
||||
import com.zhgd.jeecg.common.api.vo.Result;
|
||||
import com.zhgd.xmgl.entity.sj.JwtPayloadUserInfo;
|
||||
import com.zhgd.xmgl.entity.sj.TokenResponse;
|
||||
import com.zhgd.xmgl.modules.basicdata.service.impl.SystemUserServiceImpl;
|
||||
import com.zhgd.xmgl.util.MessageUtil;
|
||||
import com.zhgd.xmgl.util.sj.CookieUtils;
|
||||
import com.zhgd.xmgl.util.sj.JwtRsaUtils;
|
||||
import com.zhgd.xmgl.util.sj.SjUnifiedAuthenticationHttpUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 三江统一登录
|
||||
@ -31,6 +35,9 @@ public class SjLoginController {
|
||||
private SjUnifiedAuthenticationHttpUtil sjUnifiedAuthenticationHttpUtil;
|
||||
@Autowired
|
||||
private SystemUserServiceImpl systemUserService;
|
||||
@Autowired
|
||||
private StringRedisTemplate redisTemplate;
|
||||
public static String SJ_TOKEN_PREFIX = "SJ_UNIFIEDAUTHENTICATION_TOKEN:";
|
||||
|
||||
/**
|
||||
* 根据code获取token
|
||||
@ -41,16 +48,19 @@ public class SjLoginController {
|
||||
* @throws IOException
|
||||
*/
|
||||
@GetMapping("/getTokenByCode")
|
||||
public void getTokenByCode(@RequestParam String code, HttpServletResponse response, HttpServletRequest request) throws IOException {
|
||||
public void getTokenByCode(@RequestParam String code, HttpServletResponse response, HttpServletRequest request) throws IOException, InvalidKeySpecException {
|
||||
//根据授权码获取令牌
|
||||
log.info("code:{}", code);
|
||||
TokenResponse tokenByCode = sjUnifiedAuthenticationHttpUtil.getTokenByCode(code);
|
||||
//⑦将获取到的用户凭证(access_token)值存储到cookie中,名称可定为C2AT,获取到的用户刷新凭证(refresh_token)值存储到cookie中,名称为C2RT,接口返回307,重定向到应用页面(一般为首页)
|
||||
String access_token = tokenByCode.getAccess_token();
|
||||
CookieUtils.setCookie(request, response, "C2AT", access_token, Integer.valueOf(tokenByCode.getExpires_in()), "UTF-8",
|
||||
false, "192.168.34.150:8080", "/");
|
||||
CookieUtils.setCookie(request, response, "C2RT", tokenByCode.getRefresh_token(), Integer.valueOf(tokenByCode.getRe_expires_in()), "UTF-8", false,
|
||||
"192.168.34.150:8080", "/");
|
||||
if (access_token != null) {
|
||||
JwtPayloadUserInfo jwtPayloadUserInfo = JwtRsaUtils.verifyWithUserInfo(access_token);
|
||||
if (StringUtils.isNotBlank(access_token)) {
|
||||
redisTemplate.opsForValue().set(SJ_TOKEN_PREFIX + jwtPayloadUserInfo.getAc(), JSON.toJSONString(tokenByCode)
|
||||
, Long.parseLong(tokenByCode.getRe_expires_in()), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
//获取用户信息
|
||||
//重定向到应用页面(一般为首页)
|
||||
response.sendRedirect("http://192.168.34.150:8080/index.html#/login?UID=" + access_token);
|
||||
@ -67,8 +77,6 @@ public class SjLoginController {
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
log.info("logout");
|
||||
//④清除本地请求头request里面存储的cookie:C2AT、C2RT,返回302重定向到应用页面
|
||||
CookieUtils.setCookie(request, response, "C2AT", "", 0);
|
||||
CookieUtils.setCookie(request, response, "C2RT", "", 0);
|
||||
|
||||
//重定向到应用页面(一般为首页)
|
||||
response.sendRedirect("/index.html#/");
|
||||
@ -77,14 +85,16 @@ public class SjLoginController {
|
||||
/**
|
||||
* 根据token获取用户登录信息
|
||||
*
|
||||
* @param uid jwt_token
|
||||
* @param uid jwt_token 统一登录token
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("getLoginInfoByToken")
|
||||
@ResponseBody
|
||||
public Result getLoginInfoByToken(@RequestParam String uid) throws InvalidKeySpecException {
|
||||
JwtPayloadUserInfo jwtPayloadUserInfo = JwtRsaUtils.verifyWithUserInfo(uid);
|
||||
if (jwtPayloadUserInfo != null) {
|
||||
return systemUserService.sjLogin(jwtPayloadUserInfo);
|
||||
Result result = systemUserService.sjLogin(jwtPayloadUserInfo);
|
||||
return result;
|
||||
}
|
||||
return Result.error(MessageUtil.get("systemErr"));
|
||||
}
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
package com.zhgd.xmgl.security;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gexin.fastjson.JSON;
|
||||
import com.zhgd.exception.CustomException;
|
||||
import com.zhgd.xmgl.entity.sj.JwtPayloadUserInfo;
|
||||
import com.zhgd.xmgl.entity.sj.TokenResponse;
|
||||
import com.zhgd.xmgl.modules.basicdata.entity.SystemUser;
|
||||
import com.zhgd.xmgl.modules.basicdata.mapper.SystemUserMapper;
|
||||
import com.zhgd.xmgl.util.ProfileJudgeUtil;
|
||||
import com.zhgd.xmgl.util.sj.CookieUtils;
|
||||
import com.zhgd.xmgl.util.sj.JwtRsaUtils;
|
||||
import com.zhgd.xmgl.util.sj.SjUnifiedAuthenticationHttpUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@ -23,7 +28,10 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.zhgd.xmgl.modules.basicdata.controller.SjLoginController.SJ_TOKEN_PREFIX;
|
||||
|
||||
/**
|
||||
* @program: devManage
|
||||
@ -41,6 +49,10 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
private boolean securityEnable;
|
||||
@Autowired
|
||||
private SjUnifiedAuthenticationHttpUtil sjUnifiedAuthenticationHttpUtil;
|
||||
@Autowired
|
||||
private SystemUserMapper systemUserMapper;
|
||||
@Autowired
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
public static ThreadLocal<JwtPayloadUserInfo> sjUser = new ThreadLocal<>();
|
||||
|
||||
@ -54,14 +66,11 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
//三江统一认证,3.登录:过滤器判断,回调地址获取code调用获取令牌,首页根据令牌获取登录数据信息
|
||||
if (ProfileJudgeUtil.isSjjtGsx()) {
|
||||
try {
|
||||
//验证不通过不放行
|
||||
boolean b = validateSjProfile(request, response, filterChain);
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
validateSjProfile(request, response, filterChain);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
log.error("认证失败ex::", e);
|
||||
return;
|
||||
} catch (CustomException e) {
|
||||
throw new RuntimeException("认证失败");
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -82,37 +91,72 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
private boolean validateSjProfile(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws InvalidKeySpecException, IOException, ServletException {
|
||||
//不拦截url
|
||||
String permitUrls = "xmgl/sj/unifiedAuthentication/logout,xmgl/sj/unifiedAuthentication/getTokenByCode,xmgl/sj/unifiedAuthentication/getLoginInfoByToken";
|
||||
if (Arrays.asList(permitUrls.split(",")).stream().anyMatch(s -> request.getRequestURL().toString().contains(s))) {
|
||||
return true;
|
||||
private void validateSjProfile(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws InvalidKeySpecException, IOException, ServletException {
|
||||
//不传统一登录获取的token给前端,用之前的token
|
||||
//校验token
|
||||
String token = jwtTokenProvider.resolveToken(request);
|
||||
if (token == null) {
|
||||
return;
|
||||
}
|
||||
if (jwtTokenProvider.validateToken(token)) {
|
||||
Authentication auth = jwtTokenProvider.getAuthentication(token);
|
||||
//判断用户类型,统一登录还是这边登录的
|
||||
String account = auth.getName();
|
||||
SystemUser systemUser = systemUserMapper.selectOne(new LambdaQueryWrapper<SystemUser>().eq(SystemUser::getAccount, account));
|
||||
//统一登录的,redis中维护统一登录token
|
||||
Integer accountType = systemUser.getAccountType();
|
||||
if (Objects.equals(accountType, 2) || Objects.equals(accountType, 3)
|
||||
|| Objects.equals(accountType, 4) || Objects.equals(accountType, 5)) {
|
||||
//统一登录
|
||||
String tokenDetails = redisTemplate.opsForValue().get(SJ_TOKEN_PREFIX + account);
|
||||
TokenResponse tokenResponse = JSON.parseObject(tokenDetails, TokenResponse.class);
|
||||
String c2AT = tokenResponse.getAccess_token();
|
||||
String c2rt = tokenResponse.getRefresh_token();
|
||||
//②应用过滤器中判断请求头request中是否含有C2AT(若C2AT存在,C2AT的校验、过期更新请参考凭证更新令牌流程)
|
||||
//C2AT不存在,且更新令牌失败,则返回401,并在Location中带上登录页面地址,登录页面地址在应用过滤器中拼装,拼装方式请参考3.1.1获取授权码接口地址
|
||||
JwtPayloadUserInfo jwtPayloadUserInfo = null;
|
||||
if (StringUtils.isNotBlank(c2AT)) {
|
||||
//C2AT的校验
|
||||
//1.判断是否过期
|
||||
//2.令牌校验
|
||||
jwtPayloadUserInfo = JwtRsaUtils.verifyWithUserInfo(c2AT);
|
||||
sjUser.set(jwtPayloadUserInfo);
|
||||
//token校验失败,先尝试刷新token,失败就重定向统一登录
|
||||
if (jwtPayloadUserInfo == null) {
|
||||
tryRefreshToken(request, response);
|
||||
} else {
|
||||
setSjAuthenticationToken(jwtPayloadUserInfo);
|
||||
}
|
||||
} else if (StringUtils.isNotBlank(c2rt)) {
|
||||
tryRefreshToken(request, response);
|
||||
}
|
||||
|
||||
//②应用过滤器中判断请求头request中是否含有C2AT(若C2AT存在,C2AT的校验、过期更新请参考凭证更新令牌流程)
|
||||
//C2AT不存在,且更新令牌失败,则返回401,并在Location中带上登录页面地址,登录页面地址在应用过滤器中拼装,拼装方式请参考3.1.1获取授权码接口地址
|
||||
String c2AT = request.getHeader("C2AT");
|
||||
String c2rt = request.getHeader("C2RT");
|
||||
JwtPayloadUserInfo jwtPayloadUserInfo = null;
|
||||
if (StringUtils.isNotBlank(c2AT)) {
|
||||
//C2AT的校验
|
||||
//1.判断是否过期
|
||||
//2.令牌校验
|
||||
jwtPayloadUserInfo = JwtRsaUtils.verifyWithUserInfo(c2AT);
|
||||
sjUser.set(jwtPayloadUserInfo);
|
||||
//token校验失败,先尝试刷新token,失败就重定向统一登录
|
||||
if (jwtPayloadUserInfo == null) {
|
||||
return tryRefreshToken(request, response);
|
||||
} else {
|
||||
//我们这边调用我们这么认证
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
} else if (StringUtils.isNotBlank(c2rt)) {
|
||||
return tryRefreshToken(request, response);
|
||||
} else {
|
||||
//C2AT和C2RT都不存在
|
||||
//重定向登录页面
|
||||
//获取授权码,客户端申请授权的URI,在浏览器中以GET请求发送到认证服务器:
|
||||
throw new CustomException("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证方法
|
||||
*
|
||||
* @param jwtPayloadUserInfo
|
||||
*/
|
||||
private void setSjAuthenticationToken(JwtPayloadUserInfo jwtPayloadUserInfo) {
|
||||
if (jwtPayloadUserInfo != null) {
|
||||
UserDetails uds = org.springframework.security.core.userdetails.User//
|
||||
.withUsername(jwtPayloadUserInfo.getAc())//
|
||||
.password("$2a$12$LEfaQ8x1lPhxnOl3bh7hreI9o5DlV0NxDNZyazH50oji3kFE33QEi")//
|
||||
.accountExpired(false)//
|
||||
.accountLocked(false)//
|
||||
.credentialsExpired(false)//
|
||||
.authorities("admin")
|
||||
.disabled(false)//
|
||||
.build();
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(uds, "", null);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,22 +167,19 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean tryRefreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
private void tryRefreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException, InvalidKeySpecException {
|
||||
String c2rt = request.getHeader("C2RT");
|
||||
if (StringUtils.isNotBlank(c2rt)) {
|
||||
//刷新token
|
||||
TokenResponse rs = sjUnifiedAuthenticationHttpUtil.refreshToken(c2rt);
|
||||
TokenResponse tokenByCode = sjUnifiedAuthenticationHttpUtil.refreshToken(c2rt);
|
||||
//刷新token成功
|
||||
if (rs.getErrorCode() == null) {
|
||||
CookieUtils.setCookie(request, response, "C2AT", rs.getAccess_token(), Integer.valueOf(rs.getExpires_in()));
|
||||
CookieUtils.setCookie(request, response, "C2RT", rs.getRefresh_token(), Integer.valueOf(rs.getRe_expires_in()));
|
||||
return true;
|
||||
} else {
|
||||
//刷新token失败,重定向登录页面
|
||||
throw new CustomException("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||
if (tokenByCode.getErrorCode() == null) {
|
||||
JwtPayloadUserInfo jwtPayloadUserInfo = JwtRsaUtils.verifyWithUserInfo(tokenByCode.getAccess_token());
|
||||
setSjAuthenticationToken(jwtPayloadUserInfo);
|
||||
redisTemplate.opsForValue().set(SJ_TOKEN_PREFIX + jwtPayloadUserInfo.getAc(), JSON.toJSONString(tokenByCode)
|
||||
, Long.parseLong(tokenByCode.getRe_expires_in()), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user