spring security获取用户信息的实现代码
前言
我们在使用springsecurity的时候可以通过好几种方法获取用户信息,但是今天这篇文章介绍的是一个笔者觉得最优雅的实现;借鉴现有的springsecuritycontroller自动注入参数的方法,我们来进一步的实现更适合我们业务的用户信息获取方法;
思路
现在springsecurity会在controller自动注入Authentication/Userdetails等参数,我们拿到这些对象之后还需要一些处理才可以拿到我们需要的信息,例如用户ID;那获取用户ID这个步骤其实可以切片的,我们直接在controller的参数绑定之前,获取到我们需要的用户信息,然后添加到request的param里面,就可以实现获取用户信息,controller里面使用参数名可以直接接收参数;
少啰嗦,看代码
首先我们这个功能的实现遇到额第一个障碍就是默认的HttpServletRequest是没有提供修改Parameter的方法的,那么我们即使获取到用户信息也无法写入request;解决这个问题就需要自己实现一个HttpServletRequestWrapper,再使用一个Filter替换原来的request;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletRequestWrapper;
importjava.util.Enumeration;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Vector;
/**
*@authorsunhao
*@datecreatein2019-12-0914:39:52
*/
publicclassUserInfoRequestextendsHttpServletRequestWrapper{
privateMapparams=newHashMap<>();
/**
*Constructsarequestobjectwrappingthegivenrequest.
*
*@paramrequestTherequesttowrap
*
*@throwsIllegalArgumentExceptioniftherequestisnull
*/
publicUserInfoRequest(HttpServletRequestrequest){
super(request);
//将参数表,赋予给当前的Map以便于持有request中的参数
this.params.putAll(request.getParameterMap());
}
/**
*在获取所有的参数名,必须重写此方法,否则对象中参数值映射不上
*/
@Override
publicEnumerationgetParameterNames(){
returnnewVector<>(params.keySet()).elements();
}
/**
*重写getParameter方法
*
*@paramname参数名
*@return返回参数值
*/
@Override
publicStringgetParameter(Stringname){
String[]values=params.get(name);
if(values==null||values.length==0){
returnnull;
}
returnvalues[0];
}
@Override
publicString[]getParameterValues(Stringname){
String[]values=params.get(name);
if(values==null||values.length==0){
returnnull;
}
returnvalues;
}
/**
*增加参数
*
*@paramname参数名
*@paramvalue参数值
*/
publicvoidaddParameter(Stringname,Objectvalue){
if(value!=null){
if(valueinstanceofString[]){
params.put(name,(String[])value);
}elseif(valueinstanceofString){
params.put(name,newString[]{(String)value});
}else{
params.put(name,newString[]{String.valueOf(value)});
}
}
}
}
这段代码使用了乐傻驴用户的代码,在此表示感谢;然后使用Filter将原有的request替换;
@Component
publicclassUserInfoFilterextendsOncePerRequestFilter{
@Override
protectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{
filterChain.doFilter(newUserInfoRequest(request),response);
}
}
现在我们可以获取用户信息然后写入request的parameter了,这个逻辑是在filter里实现还是在interceptor里实现就看读者自己的想法了;笔者系统里面有多种用户,获取用户信息的逻辑有所不同,所以笔者选择使用interceptor来实现,可以通过自定义注解来控制注入哪种用户信息;
@Component
publicclassUserInfoInterceptorimplementsHandlerInterceptor{
@Override
publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler){
Methodmethod=((HandlerMethod)handler).getMethod();
AdminUserInfoadminUserInfo=method.getDeclaredAnnotation(AdminUserInfo.class);
if(adminUserInfo!=null){
//获取用户信息的逻辑自由发挥
LonguserId=((Admin)((OAuth2Authentication)request.getUserPrincipal()).getPrincipal()).getId();
//将用户信息写入request的parameter
((UserInfoRequest)request).addParameter("userId",userId);
returntrue;
}
EmployeeUserInfoemployeeUserInfo=method.getDeclaredAnnotation(EmployeeUserInfo.class);
if(employeeUserInfo!=null){
LonguserId=((Employee)((OAuth2Authentication)request.getUserPrincipal()).getPrincipal()).getId();
((UserInfoRequest)request).addParameter("userId",userId);
returntrue;
}
returntrue;
}
}
上面我自己写了两个注解,这两个注解的代码我就不贴出来了,写这两个注解完全就是为了注入不同的用户信息;大家可以各自发挥,注解不是必须的,如果大家系统里面只有一种用户或者由于其他原因可以直接注入parameter;接下来配置interceptor
@Configuration
publicclassWebMvcConfigimplementsWebMvcConfigurer{
privatefinalUserInfoInterceptoruserInfoInterceptor;
publicWebMvcConfig(UserInfoInterceptoruserInfoInterceptor){
this.userInfoInterceptor=userInfoInterceptor;
}
@Override
publicvoidaddInterceptors(InterceptorRegistryregistry){
registry.addInterceptor(userInfoInterceptor);
}
}
代码写到这里功能已经做完了,我们可以在controller里面这样获取用户信息
@EmployeeUserInfo//自定义注解
@GetMapping
publicvoidtestObtainUserInfo(LonguserId){
System.out.println("userId="+userId);
}
写EmployeeUserInfo注解注入的就是employee的用户信息,写AdminUserInfo注解注入的就是admin的用户信息
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。