提交 7166c8b4 编写于 作者: ibiz4j's avatar ibiz4j

cloud uaa 接入

上级 02d9b4c7
......@@ -47,8 +47,8 @@ public class IBZUSERServiceImpl extends ServiceImpl<IBZUSERMapper, IBZUSER> impl
conds.eq("domains",domains);
}
IBZUSER user = this.getOne(conds);
if (user == null) {
throw new UsernameNotFoundException("用户" + username + "未找到");
if(user == null) {
throw new BadRequestAlertException("登录失败","IBZUSER",username);
}
else {
user.setUsername(username);
......
......@@ -4,6 +4,7 @@ import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.lang.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -22,15 +23,20 @@ public class CustomJacksonSerializer<T> extends Jackson2JsonRedisSerializer<T>
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
public T deserialize(@Nullable byte[] bytes) throws SerializationException {
if ( bytes==null || bytes.length==0) {
return null;
}
String serializerContent = new String(bytes, DEFAULT_CHARSET);
Matcher matcher = Pattern.compile(DEFAULT_PACKAGE).matcher(serializerContent);
if(matcher.find()){
serializerContent=serializerContent.replaceAll(DEFAULT_PACKAGE,USER_PACKAGE);
super.deserialize(serializerContent.getBytes());
}
if(serializerContent.contains(CLASSNAME_EX)){
serializerContent=serializerContent.replaceAll(CLASSNAME_EX_PATTEN,"");
super.deserialize(serializerContent.getBytes());
}
return super.deserialize(serializerContent.getBytes());
return super.deserialize(bytes);
}
}
......@@ -5,6 +5,8 @@ import cn.ibizlab.util.security.AuthorizationLogin;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class IBZUAAFallback implements IBZUAAFeignClient {
......@@ -13,6 +15,11 @@ public class IBZUAAFallback implements IBZUAAFeignClient {
return null;
}
@Override
public Map getAppData() {
return null;
}
@Override
public AuthenticationUser login(AuthorizationLogin authorizationLogin) {
return null;
......
......@@ -7,6 +7,8 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@FeignClient(value = "${ibiz.ref.service.uaa:ibzuaa-api}",contextId = "uaa",fallback = IBZUAAFallback.class)
public interface IBZUAAFeignClient
{
......@@ -18,6 +20,11 @@ public interface IBZUAAFeignClient
@PostMapping("/syspssystems/save")
Boolean syncSysAuthority(@RequestBody JSONObject system);
@GetMapping(value = "/appdata")
Map getAppData();
/**
* 用户登录
* @param authorizationLogin 登录信息
......
package cn.ibizlab.util.errors;
import org.zalando.problem.AbstractThrowableProblem;
import org.zalando.problem.Status;
public class ForbiddenException extends AbstractThrowableProblem {
public ForbiddenException(String message) {
super(ErrorConstants.DEFAULT_TYPE, message, Status.FORBIDDEN);
}
}
package cn.ibizlab.util.errors;
import org.zalando.problem.AbstractThrowableProblem;
import org.zalando.problem.Status;
public class UnauthorizedException extends AbstractThrowableProblem {
public UnauthorizedException(String message) {
super(ErrorConstants.DEFAULT_TYPE, message, Status.UNAUTHORIZED);
}
}
......@@ -28,43 +28,8 @@ public class AppController {
@Autowired
private AuthenticationUserService userDetailsService;
@RequestMapping(method = RequestMethod.GET, value = "/appdata")
public ResponseEntity<JSONObject> getAppData() {
JSONObject appData = new JSONObject() ;
Set<String> appMenu = new HashSet();
Set<String> uniRes = new HashSet();
AuthenticationUser curUser = AuthenticationUser.getAuthenticationUser();
if(enablePermissionValid&&(!ObjectUtils.isEmpty(systemId))){
Collection<GrantedAuthority> authorities=curUser.getAuthorities();
Iterator it = authorities.iterator();
while(it.hasNext()) {
GrantedAuthority authority = (GrantedAuthority)it.next();
String strAuthority=authority.getAuthority();
if(strAuthority.startsWith("UNIRES_"+systemId)) {
uniRes.add(strAuthority.substring(systemId.length()+8));
}
else if(strAuthority.startsWith("APPMENU_"+systemId)){
appMenu.add(strAuthority.substring(systemId.length()+9));
}
}
}
Map<String,Object> context = new HashMap<>();
context.putAll(curUser.getSessionParams());
context.put("srfusername",curUser.getPersonname());
appData.put("context",context);
appData.put("unires",uniRes);
appData.put("appmenu",appMenu);
appData.put("enablepermissionvalid",enablePermissionValid);
if(curUser.getSuperuser()==1){
appData.put("enablepermissionvalid",false);
}
else{
appData.put("enablepermissionvalid",enablePermissionValid);
}
fillAppData(appData);
return ResponseEntity.status(HttpStatus.OK).body(appData);
public ResponseEntity<Map> getAppData() {
return ResponseEntity.status(HttpStatus.OK).body(userDetailsService.getAppData());
}
@RequestMapping(method = RequestMethod.GET, value = "${ibiz.auth.logoutpath:v7/logout}")
......@@ -74,12 +39,4 @@ public class AppController {
}
}
/**
* 应用参数扩展
* @param appData
*/
protected void fillAppData(JSONObject appData){
}
}
package cn.ibizlab.util.security;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.*;
import io.jsonwebtoken.impl.DefaultClock;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
......@@ -172,7 +173,7 @@ public class AuthenticationUser implements UserDetails
/**
* 是否为超级管理员
*/
private int superuser;
private int superuser=0;
/**
* 用户权限资源
*/
......@@ -181,6 +182,7 @@ public class AuthenticationUser implements UserDetails
* 用户上下文参数
*/
@JsonIgnore
@JSONField(serialize = false)
private Map<String,Object> userSessionParam;
/**
* 当前用户上下级组织信息
......@@ -203,10 +205,22 @@ public class AuthenticationUser implements UserDetails
*/
private String sdept;
private Integer apiuser=0;
private String dcsystemid;
private String tenant;
private String token;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", locale = "zh" , timezone="GMT+8")
@JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date expiration;
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
return expiration==null?true:(!expiration.before(DefaultClock.INSTANCE.now()));
}
@JsonIgnore
......@@ -232,6 +246,8 @@ public class AuthenticationUser implements UserDetails
return true;
}
public static AuthenticationUser getAuthenticationUser()
{
if(SecurityContextHolder.getContext()==null||SecurityContextHolder.getContext().getAuthentication()==null||SecurityContextHolder.getContext().getAuthentication().getPrincipal()==null){
......@@ -271,6 +287,8 @@ public class AuthenticationUser implements UserDetails
if(this.sessionParams==null)
{
sessionParams = getUserSessionParam();
sessionParams.put("srfdcid", this.getTenant());
sessionParams.put("srfdcsystemid", this.getDcsystemid());
sessionParams.put("srfsystemid",this.getSrfsystemid());
sessionParams.put("srfpersonid", this.getUserid());
sessionParams.put("srfpersonname", this.getPersonname());
......@@ -353,4 +371,26 @@ public class AuthenticationUser implements UserDetails
}
}
@JsonAnyGetter
@JSONField(name = "_any", unwrapped = true, serialize = true, deserialize = false)
public Map<String , Object> any() {
return userSessionParam;
}
@JsonAnySetter
@JSONField(name = "_any", unwrapped = true, serialize = false, deserialize = true)
public void set(String field, Object value) {
this.userSessionParam.put(field,value);
}
public Object get(String field) {
return this.userSessionParam.get(field);
}
}
......@@ -113,8 +113,11 @@ public class SimpleTokenUtil implements AuthTokenUtil,Serializable {
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
user.setToken(token);
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
final Date expiration = getExpirationDateFromToken(token);
user.setExpiration(expiration);
return !expiration.before(clock.now());
}
private Date calculateExpirationDate(Date createdDate) {
......
package cn.ibizlab.util.security;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = UAADEAuthority.class, name= UAAGrantedAuthority.TYPE_OPPRIV),
@JsonSubTypes.Type(value = UAAMenuAuthority.class, name= UAAGrantedAuthority.TYPE_APPMENU),
@JsonSubTypes.Type(value = UAAUniResAuthority.class, name= UAAGrantedAuthority.TYPE_UNIRES),
@JsonSubTypes.Type(value = UAARoleAuthority.class, name= UAAGrantedAuthority.TYPE_ROLE)
})
public class UAAGrantedAuthority implements GrantedAuthority {
public final static String TYPE_OPPRIV = "OPPRIV";
public final static String TYPE_UNIRES = "UNIRES";
public final static String TYPE_APPMENU = "APPMENU";
public final static String TYPE_ROLE = "ROLE";
private String name;
private String type ;
private String systemid;
......
......@@ -67,10 +67,6 @@ public class UAATokenUtil implements AuthTokenUtil, Serializable {
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
public String generateToken(UserDetails userDetails) {
return null;
......@@ -78,8 +74,12 @@ public class UAATokenUtil implements AuthTokenUtil, Serializable {
public Boolean validateToken(String token, UserDetails userDetails) {
AuthenticationUser user = (AuthenticationUser) userDetails;
user.setToken(token);
final Date created = getIssuedAtDateFromToken(token);
return (!isTokenExpired(token) );
final Date expiration = getExpirationDateFromToken(token);
user.setExpiration(expiration);
return !expiration.before(clock.now());
}
......
......@@ -2,9 +2,16 @@ package cn.ibizlab.util.service;
import cn.ibizlab.util.security.AuthenticationUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.util.ObjectUtils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
public interface AuthenticationUserService extends UserDetailsService {
......@@ -23,5 +30,57 @@ public interface AuthenticationUserService extends UserDetailsService {
@CacheEvict( value="ibzuaa_users", key = "'getByUsername:'+#p0")
default void resetByUsername(String username){}
@Value("${ibiz.enablePermissionValid:false}")
boolean enablePermissionValid = false; //是否开启权限校验
@Value("${ibiz.systemid}")
String systemId = "";
default Map getAppData()
{
Map appData = new HashMap() ;
Set<String> appMenu = new HashSet();
Set<String> uniRes = new HashSet();
AuthenticationUser curUser = AuthenticationUser.getAuthenticationUser();
if(enablePermissionValid&&(!ObjectUtils.isEmpty(systemId))){
Collection<GrantedAuthority> authorities=curUser.getAuthorities();
Iterator it = authorities.iterator();
while(it.hasNext()) {
GrantedAuthority authority = (GrantedAuthority)it.next();
String strAuthority=authority.getAuthority();
if(strAuthority.startsWith("UNIRES_"+systemId)) {
uniRes.add(strAuthority.substring(systemId.length()+8));
}
else if(strAuthority.startsWith("APPMENU_"+systemId)){
appMenu.add(strAuthority.substring(systemId.length()+9));
}
}
}
if (!ObjectUtils.isEmpty(curUser.getExpiration())) {
// yyyy-MM-dd HH:mm:ss
DateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
appData.put("expireddate", dtFormat.format(curUser.getExpiration()));
}
Map<String,Object> context = new HashMap<>();
context.putAll(curUser.getSessionParams());
context.put("srfusername",curUser.getPersonname());
appData.put("context",context);
appData.put("unires",uniRes);
appData.put("appmenu",appMenu);
appData.put("enablepermissionvalid",enablePermissionValid);
if(curUser.getSuperuser()==1){
appData.put("enablepermissionvalid",false);
}
else{
appData.put("enablepermissionvalid",enablePermissionValid);
}
fillAppData(appData);
return appData;
}
default void fillAppData(Map appData) {}
}
package cn.ibizlab.util.service;
import cn.ibizlab.util.cache.redis.CustomJacksonSerializer;
import cn.ibizlab.util.client.IBZUAAFeignClient;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.errors.UnauthorizedException;
import cn.ibizlab.util.security.*;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.TypeUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@Service("CloudUserService")
@ConditionalOnExpression("${ibiz.enablePermissionValid:false}||'${ibiz.auth.service:IBZUAAUserService}'.equals('CloudUserService')")
public class CloudUserService extends IBZUAAUserService {
@Autowired
@Lazy
private RedisTemplate redisTemplate;
@Value("${ibiz.jwt.header:Authorization}")
private String tokenHeader;
private ObjectMapper objectMapper=new ObjectMapper();
private TypeReference<Collection<UAAGrantedAuthority>> UAAGrantedAuthorityListType = new TypeReference<Collection<UAAGrantedAuthority>>(){};
@Override
public AuthenticationUser loadUserByUsername(String username) {
Object obj = redisTemplate.opsForValue().get("ibiz-cloud-uaa-user-" + username);
if (obj == null) {
throw new BadRequestAlertException("登录失败", "CloudUser", username);
}
try {
AuthenticationUser dcEmployee = objectMapper.readValue(objectMapper.writeValueAsBytes(obj), AuthenticationUser.class);
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
final String requestHeader = request.getHeader(this.tokenHeader);
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
String authToken = requestHeader.substring(7);
// 重新计算用户标识
String srforgid = request.getHeader("srforgid");
String srfsystemid = request.getHeader("srfsystemid");
String srfdcsystemid = request.getHeader("srfdcsystemid");
String srfuserid = request.getHeader("srfuserid");
String srfdcid = request.getHeader("srfdcid");
if ("undefined".equals(srfsystemid)) {
srfsystemid = null;
}
if ("undefined".equals(srforgid)) {
srforgid = null;
}
Collection<? extends GrantedAuthority> authorities = null;
if (StringUtils.hasLength(srfsystemid)
&& StringUtils.hasLength(srfdcid) && StringUtils.hasLength(srfdcsystemid) && StringUtils.hasLength(srfuserid)) {
//可以没有组织
//&& StringUtils.hasLength(srforgid)
if ((dcEmployee.getApiuser() == 1)
|| (dcEmployee.getSuperuser() == 1)) {
String srfusername = request.getHeader("srfusername");
//接口用户用传入身份构造EMP
dcEmployee.setSrfdcid(srfdcid);
dcEmployee.setUserid(srfuserid);
dcEmployee.setDcsystemid(srfdcsystemid);
if (StringUtils.hasLength(srfusername)) {
try {
dcEmployee.setPersonname(URLDecoder.decode(srfusername, "UTF-8"));
} catch (Exception ex) {
log.error(ex.getMessage());
dcEmployee.setPersonname(srfusername);
}
}
dcEmployee.setOrgid(srforgid);
String strValue = request.getHeader("srforgcode");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setOrgcode(strValue);
}
strValue = request.getHeader("srfdeptid");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setMdeptid(strValue);
}
strValue = request.getHeader("srfdeptcode");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setMdeptcode(strValue);
}
strValue = request.getHeader("srfporgids");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setPorg(strValue);
}
strValue = request.getHeader("srfsorgids");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setSorg(strValue);
}
strValue = request.getHeader("srfpdeptids");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setPdept(strValue);
}
strValue = request.getHeader("srfsdeptids");
if (StringUtils.hasLength(strValue)) {
dcEmployee.setSdept(strValue);
}
} else {
log.error(String.format("用户[%1$s][%2$s]使用API模式访问系统", dcEmployee.getUserid(), dcEmployee.getUsername()));
throw new UnauthorizedException(String.format("用户[%1$s][%2$s]使用API模式访问系统", dcEmployee.getUserid(), dcEmployee.getUsername()));
}
} else if (StringUtils.hasLength(srfsystemid) && StringUtils.hasLength(srforgid)) {
AuthenticationUser employee = this.getEmployee(srfsystemid, srforgid, dcEmployee.getUsername(), authToken);
if (employee != null ) {
if(dcEmployee.getSuperuser() == 1)
employee.setSuperuser(1);
dcEmployee=employee;
}
String strDCSystemId = null;
if (dcEmployee != null) {
strDCSystemId = dcEmployee.getDcsystemid();
}
if (StringUtils.hasLength(strDCSystemId)) {
authorities = this.getGrantedAuthorities(strDCSystemId, dcEmployee.getUsername(), authToken);
if(!ObjectUtils.isEmpty(authorities)) {
dcEmployee.setAuthorities((Collection) authorities);
JSONObject permission =new JSONObject();
permission.put("authorities",authorities);
dcEmployee.setPermissionList(permission);
}
}
}
}
}
return dcEmployee;
} catch (IOException e) {
throw new BadRequestAlertException("登录失败", "CloudUser", username);
}
}
protected Collection<UAAGrantedAuthority> getGrantedAuthorities(String strDCSystemId, String strUAAUserName, String strToken){
String strCacheCat = String.format("ibiz-cloud-uaa-cat-%2$s--%3$s", strUAAUserName, DigestUtils.md5DigestAsHex(strToken.getBytes(StandardCharsets.UTF_8)));;
String strCacheTag = String.format("authorities-%1$s", strDCSystemId);
Object obj = this.redisTemplate.opsForHash().get(strCacheCat, strCacheTag);
if(!ObjectUtils.isEmpty(obj)) {
try {
return objectMapper.readValue(objectMapper.writeValueAsString(obj), this.UAAGrantedAuthorityListType);
} catch (IOException e) {
}
}
return null;
}
protected AuthenticationUser getEmployee(String strSystemId, String strOrgId, String strUAAUserName, String strToken) {
String strCacheCat = String.format("ibiz-cloud-uaa-cat-%2$s--%3$s", strUAAUserName, DigestUtils.md5DigestAsHex(strToken.getBytes(StandardCharsets.UTF_8)));;
String strCacheTag = String.format("sysemp-%1$s--%2$s", strSystemId, strOrgId);
Object obj = this.redisTemplate.opsForHash().get(strCacheCat, strCacheTag);
if(!ObjectUtils.isEmpty(obj)) {
try {
return objectMapper.readValue(objectMapper.writeValueAsString(obj), AuthenticationUser.class);
} catch (IOException e) {
}
}
return null;
}
@Autowired
private IBZUAAFeignClient uaaFeignClient;
@Override
public Map getAppData() {
Map appData = uaaFeignClient.getAppData();
return ObjectUtils.isEmpty(appData)?super.getAppData():appData;
}
}
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册