作者 朱兆平

add: 增加对机场统一认证接口

... ... @@ -151,7 +151,8 @@ logging:
#Java Web Token 时效时间,单位秒
jwt:
max-alive: 30000
sso:
url: http://10.5.14.103:27080/sso/p3/serviceValidate
info:
version: 2.0
description: "统一用户认证中心服务,具备用户认证,接口鉴权|数据鉴权功能."
... ...
... ... @@ -144,7 +144,8 @@ logging:
#Java Web Token 时效时间,单位秒
jwt:
max-alive: 30000
sso:
url: http://10.5.14.103:27080/sso/p3/serviceValidate
info:
version: 2.0
description: "具有公司及部门管理级别的用户管理中心"
... ...
... ... @@ -7,9 +7,15 @@ package com.tianbo.warehouse;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
@SpringBootApplication
@EnableScheduling
... ... @@ -22,5 +28,10 @@ public class WarehouseApplication {
SpringApplication.run(WarehouseApplication.class, args);
}
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.setConnectTimeout(Duration.ofSeconds(15)).setReadTimeout(Duration.ofSeconds(15))
.build();
}
}
... ...
... ... @@ -2,21 +2,33 @@ package com.tianbo.warehouse.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.thoughtworks.xstream.core.util.Base64Encoder;
import com.tianbo.warehouse.controller.response.ResultJson;
import com.tianbo.warehouse.model.ROLE;
import com.tianbo.warehouse.model.Token;
import com.tianbo.warehouse.model.USERS;
import com.tianbo.warehouse.security.filter.JwtTokenUtil;
import com.tianbo.warehouse.service.PermissionService;
import com.tianbo.warehouse.service.RoleService;
import com.tianbo.warehouse.service.UserService;
import com.tianbo.warehouse.util.RedisUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.imageio.ImageIO;
... ... @@ -34,11 +46,35 @@ public class AnonymousController {
RoleService roleService;
@Autowired
private PermissionService permissionService;
@Autowired
RedisUtils redisUtils;
@Autowired
private DefaultKaptcha captchaProducer;
@Autowired
RestTemplate restTemplate;
@Value("${sso.url}")
private String SSOUrl;
@Value("${jwt.max-alive}")
protected Integer jwtMaxAlive;
@Autowired
UserService userService;
/**
* SSO验证服务票据响应属性名
*/
private static final String SERVICE_RESPONESE = "serviceResponse";
private static final String AUTHENTICATION_SUCCESS = "authenticationSuccess";
private static final String LOGIN_NAME = "LOGIN_NAME";
private static final String ATTRIBUTES = "attributes";
private static final String USER_ID = "USER_ID";
/**
* 配置匿名者可以访问的路由,并更新到redis,匿名者默认可以访问的role_name =ROLE_anonymous
* 此方法会将所有符合权限组名=ROLE_anonymous的权限更新到redis中,供gateway调用判断权限
... ... @@ -85,4 +121,126 @@ public class AnonymousController {
return new ResultJson("200","verify get ok",map,verifyToken);
}
@ApiOperation(value = "查询用户列表及信息", notes = "查询用户列表及单个用户信息")
@RequestMapping("ssoTicket")
public ResultJson ssoLogin(@RequestParam("ticket") String ticket,
@RequestParam("myWebLoginUrl") String myWebLoginUrl
){
try {
log.info("[SSO-AUTH-TICKET]-开始单点登录票据认证-[{}]",ticket);
// 构建接口地址
String url = SSOUrl+"?format=json&service="
+ myWebLoginUrl
+ "&ticket=" + ticket;
// 使用RestTemplate调用接口
RestTemplate restTemplate = new RestTemplate();
/**
* 单点登录认证返回实体类
* {
* "serviceResponse" : {
* "authenticationSuccess" : {
* "user" : "zhangyf",
* "attributes" : {
* "isFromNewLogin" : [ false ],
* "authenticationDate" : [ 1.614564403617E9 ],
* "successfulAuthenticationHandlers" : [ "pwd" ],
* "USER_ID" : "8a0162a628aa4049a7840d75378f1a91",
* "USER_NAME" : "张炎锋",
* "extend" : [ ],
* "credentialType" : "UsernamePasswordCredential",
* "samlAuthenticationStatementAuthMethod" : "urn:oasis:names:tc:SAML:1.0:am:password",
* "ipTerritory" : "",
* "authenticationMethod" : "pwd",
* "equipType" : "pc",
* "clientIp" : "172.19.0.17",
* "isDefaultPwd" : "false",
* "longTermAuthenticationRequestTokenUsed" : [ false ],
* "LOGIN_NAME" : "zhangyf",
* "MOBILE" : "18739902467"
* }
* }
* }
* },
*/
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
String responseBody = responseEntity.getBody();
try {
JSONObject jsonObject = JSONObject.parseObject(responseBody);
USERS user = parseSSOObject(jsonObject);
if (StringUtils.isNotEmpty(user.getUsername())){
USERS loginUser = userService.loadByUsername(user.getUsername());
if (loginUser!=null && loginUser.getUserId()>-1){
log.info("[SSO-AUTH-TICKET]-从认证中心获取到用户[{}]信息,开始设置系统登录认证token",user.getUsername());
user.setUserId(loginUser.getUserId());
user.setUsername(loginUser.getUsername());
user.setUserface(loginUser.getUserface());
user.setUserId(loginUser.getUserId());
user.setRealname(loginUser.getRealname());
user.setCompanyId(loginUser.getCompanyId());
user.setCompanyName(loginUser.getCompanyName());
user.setCompanyInfo(loginUser.getCompanyInfo());
user.setUserStatus(loginUser.getUserStatus());
user.setState(loginUser.getState());
}else {
user.setPassword("sso");
user.setUserStatus(2);
user.setState(true);
userService.insertSelective(user);
}
//设置用户的TOKEN的有效时间,时间配置在配置文件中设置
int expirationSeconds = 3600*24*7;
String jwtToken = JwtTokenUtil.generateToken(user.getUsername(), jwtMaxAlive);
user.setToken(jwtToken);
//这里将登录成功的[user]对象数据写入redis缓存,KEY为token value为user的JSON对象
String json = JSON.toJSONString(loginUser);
redisUtils.set(jwtToken, json,expirationSeconds);
redisUtils.set(Token.USER_TOKEN_KEY + user.getUsername(),jwtToken,expirationSeconds);
Map<String,Object> menuMap = permissionService.getUserMenus(user.getUserId());
return new ResultJson("200","单点登录认证成功",user);
}
} catch (JSONException e) {
e.printStackTrace();
log.error("[SSO-AUTH-TICKET-ERR]-单点登录票据解析异常",e);
return new ResultJson("400","单点登录票据解析异常",e.getMessage());
}
}catch (Exception e){
e.printStackTrace();
log.error("[SSO-AUTH-TICKET-ERR]-单点登录票据认证异常",e);
}
return new ResultJson("401","单点登录票据认证失败");
}
/**
* 解析单点认证返回的信息
* @param ssoResp 返回实体类
* @return 用户类
*/
private USERS parseSSOObject(JSONObject ssoResp){
USERS user = new USERS();
// 根节点
if (ssoResp.containsKey(SERVICE_RESPONESE)){
JSONObject root = ssoResp.getJSONObject(SERVICE_RESPONESE);
//成功节点
if (root.containsKey(AUTHENTICATION_SUCCESS)){
JSONObject auth = root.getJSONObject(AUTHENTICATION_SUCCESS);
//用户名获取
String userName = auth.getString("user");
//用户其他属性
JSONObject attributes = auth.getJSONObject(ATTRIBUTES);
String loginName = attributes.getString(LOGIN_NAME);
String userId = attributes.getString(USER_ID);
String realName = attributes.getString("USER_NAME");
log.info("[SSO-AUTH-TICKET-INFO]-用户:{}/{}",loginName,realName);
user.setUsername(loginName);
// user.setUserId(userId);
}
}
return user;
}
}
... ...
... ... @@ -57,7 +57,7 @@ public class SM3EncryptUtil {
public static void main(String[] args) {
Security.addProvider(new BouncyCastleProvider());
try {
String pwdDigest = passwordSm3("vmvnv1v2");
String pwdDigest = passwordSm3("jc12345");
System.out.println(pwdDigest);
} catch (Exception e) {
e.printStackTrace();
... ...
package com.tianbo.warehouse;
import com.tianbo.warehouse.security.config.SM3PasswordEncoder;
import com.tianbo.warehouse.security.login.SM4EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WarehouseApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
public class SM3EncodeTest {
@Test
public void encode(){
String password = "vmvnv1v2VV";
SM3PasswordEncoder encoder =new SM3PasswordEncoder();
String encode = encoder.encode(password);
System.out.println("SM3encode = " + encode);
String SM4encode = new SM4EncryptUtil().pwd(password);
System.out.println("SM4encode = " + SM4encode);
... ...