集成统一身份认证(auth2)
通过用户输入的账号或者密码,调用统一身份认证接口获取code,通过code获取token,解析token获取对应登录账号,根据账号获取登录人员对应权限信息。(未获取到code走注册流程)
jwt生成token
根据获取的人员ID,姓名等等通过jwtTokenUtil生成对应token
JWTInfo jwtInfo = jwtTokenUtil.getJwtInfo(userMap,username,userid,name,sap);
newToken = jwtTokenUtil.generateToken(jwtInfo);
token验证
每次接口访问增加拦截器,验证token是否可用
1、继承HandlerInterceptorAdapter类
preHandle:在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true,则继续调用下一个拦截器。如果返回false,则中断执行,也就是说我们想调用的方法 不会被执行,但是你可以修改response为你想要的响应。
postHandle:在方法执行后调用。
afterCompletion:在整个请求处理完毕后进行回调,也就是说视图渲染完毕或者调用方已经拿到响应。
@Slf4j
@Component
public class UserAuthRestInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(UserAuthRestInterceptor.class);
@Autowired
private UserAuthUtil userAuthUtil;
@Autowired
private UserAuthConfig userAuthConfig;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(!(handler instanceof HandlerMethod))return true;
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 配置该注解,说明不进行用户拦截
IgnoreUserToken annotation = handlerMethod.getBeanType().getAnnotation(IgnoreUserToken.class);
if (annotation == null) {
annotation = handlerMethod.getMethodAnnotation(IgnoreUserToken.class);
}
if(annotation!=null) {
return super.preHandle(request, response, handler);
}
String token = request.getHeader(userAuthConfig.getTokenHeader());
if(StringUtils.isNotBlank(token)){
try {
IJWTInfo infoFromToken = userAuthUtil.getInfoFromToken(token);
BaseContextHandler.setUsername(infoFromToken.getUniqueName());
BaseContextHandler.setName(infoFromToken.getName());
BaseContextHandler.setUserID(infoFromToken.getId());
BaseContextHandler.setSap(infoFromToken.getSap());
BaseContextHandler.setTenantId(infoFromToken.getTenantId());
BaseContextHandler.setMaxOrgCode(infoFromToken.getMaxOrgCode());
BaseContextHandler.setBizType(infoFromToken.getBizType());
//add by changweican 20190218 添加组织机构编码做灰度发布用
BaseContextHandler.setOrgCode(infoFromToken.getOrgCode());
BaseContextHandler.setToken(token);
} catch (Exception e) {
logger.error("fail to parse token:"+token,e);
}
}
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
BaseContextHandler.remove();
super.afterCompletion(request, response, handler, ex);
}
}
2、继承WebMvcConfigurer配置拦截器
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
ArrayList<String> commonPathPatterns = getExcludeCommonPathPatterns();
registry.addInterceptor(getUserAuthRestInterceptor()).addPathPatterns("/**").excludePathPatterns(commonPathPatterns.toArray(new String[]{}));
super.addInterceptors(registry);
}
@Bean
UserAuthRestInterceptor getUserAuthRestInterceptor(){
return new UserAuthRestInterceptor();
}
private ArrayList<String> getExcludeCommonPathPatterns(){
ArrayList<String> list = new ArrayList<>();
String[] urls = {"/token"};
Collections.addAll(list,urls);
return list;
}
}
feignclient 接口调用-token传递
1、在调用服务中新建FeignConfig类并实现RequestInterceptor接口,重写apply方法即可
@Slf4j
@Component
public class ServiceFeignInterceptor implements RequestInterceptor {
private Logger logger = LoggerFactory.getLogger(ServiceFeignInterceptor.class);
@Autowired
private UserAuthConfig userAuthConfig;
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header(userAuthConfig.getTokenHeader(), BaseContextHandler.getToken());
}
}