作为一个小外包...,记录一下工作中常用的一些方法(tools),以便后续使用。
如果有小伙伴看,欢迎指点。但是不要指指点点。。
我觉得在外包项目中用的一般是单点登录,各个单点的交互部分还是有些不相同的...
我个人觉得单点服务携带凭证跳转到子系统前端页面更合适,由前端再发起Ajax请求到子系统后端,凭借票据换取用户信息,并存储到子系统
总的来说后端都是通过ticket换取用户信息,缓存到本系统来进行登陆控制和权限控制。
完整代码见GIT(https://github.com/201811050890/OutResourceBoy/tree/login-permission)
登录核心
/**
* 单点登陆
* 情况2:sso服务端,先跳转到子系统的前端。前端把ticket再回传
*
* @param ticket 票据(一般来说都是给个ticket,最多就改个名字【比如:code】。当然可能会传其他的参数)
*/
@RequestMapping("/login2")
@ResponseBody
public RespBean mySsoLogin(@RequestParam(value = "ticket") String ticket){
if (StrUtil.isBlank(ticket)){
// 抛个异常,记个日志。。。
throw new RuntimeException("异常");
}
// --- LoginServiceImpl.java --- //
HttpResponse ticketRes = HttpRequest.get("https://sso-server.com/checkTicket").form("ticket", ticket).execute();
if (ObjectUtil.equals(ticketRes.getStatus(), HttpStatus.HTTP_OK)){
// 1、获取sso-server相应结果 --> 有些是直接返回用户信息,也可能是用户的一个标识,还需要我们进一步处理
String body = ticketRes.body();
// 2、映射成实体类
MyUser myUser = JSONUtil.toBean(body, MyUser.class);
// 3、生成token给前端
String cacheToken = IdUtil.fastSimpleUUID();
String encryptToken = TokenUtil.encrypt(new LoginEncryptBO(cacheToken, System.currentTimeMillis()));
// 4、缓存到Redis
MyRedisUtil.set(CacheConstant.ACCESS_TOKEN_PREFIX + cacheToken, myUser, CacheConstant.EXPIRE_TIME);
// 5、登录日志 等业务
// ......
LoginUserUtils.addCurrentUser(myUser);
// 6、返回json给前端
return RespBean.success(encryptToken);
}
return RespBean.error(RespBeanEnum.ERROR);
}
鉴权核心代码
@Pointcut("@annotation(my.aop.Permission)")
public void permissionPoint() {
}
/**
* 判断用户是否有权限
* <p>
* 这里用户是否登录未做判断
* </p>
*
* @param joinPoint 切点
*/
@Before(value = "permissionPoint()")
public void hasPermission(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Permission permission = method.getAnnotation(Permission.class);
String[] roles = permission.roles();
ArrayList<String> permRoles = ListUtil.toList(roles);
if (CollectionUtil.isEmpty(permRoles)) {
return;
}
MyUser currentUser = LoginUserUtils.getCurrentUser();
List<String> loginUserRoles = currentUser.getRoleList();
RoleConcatConstant concat = permission.concat();
judgeRoles(concat, permRoles, loginUserRoles);
}
/**
* 判断权限
*
* @param concat 权限之间的连接情况【OR或AND】
* @param permRoles 当前方法所需的Role
* @param loginUserRoles 当前登录用户拥有的Role
*/
private void judgeRoles(RoleConcatConstant concat, ArrayList<String> permRoles, List<String> loginUserRoles) {
HashSet<String> permRoleSet = new HashSet<>(permRoles);
if (ObjectUtil.equal(concat, RoleConcatConstant.OR)) {
boolean b = permRoleSet.stream().anyMatch(loginUserRoles::contains);
if (!b) {
throw new ServiceException(RespBean.error(RespBeanEnum.NO_ROLES));
}
} else if (ObjectUtil.equal(concat, RoleConcatConstant.AND)) {
boolean b = new HashSet<>(loginUserRoles).containsAll(permRoleSet);
if (!b) {
throw new ServiceException(RespBean.error(RespBeanEnum.NO_ROLES));
}
}
}