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 publicEnumeration getParameterNames(){ 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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。