使用JSON格式数据的SpringSecurity登录方法
使用SpringSecurity时,大家都知道默认的登录数据是以键/值的形式传输的。默认情况下,不支持JSON格式的登录数据。如果有这样的要求,需要自己解决。这篇文章主要和你的朋友谈论这个话题。
基本登录方案
在讨论如何使用JSON登录之前,我们先来看一下基本的登录。为了简单起见,SpringSecurity不连接正在使用的数据库,直接在内存中配置用户名和密码。具体操作步骤如下:
创建春季开机项目
首先,创建SpringBoot项目并添加SpringSecurity依赖项,如下所示:
相关性groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-Security/artifactId/Dependency相关性groupIdorg.springframework.boot/groupId工件ID Spring-boot-starter-web/工件Id/Dependency添加安全性配置
创建安全性配置并完成SpringSecurity的配置,如下所示:
@配置公共类安全配置扩展了web security configureradapter { @ Bean passwordencode passwordencode(){ 0返回新的bcryptpasswordencode();} @覆盖受保护的空配置(AuthenticationManagerBuilder auth)引发异常{ auth.inMemoryAuthentication().withUser('张三')。密码(' 2a $ 10 $ 2O4EwLrrFPEboTfDOtC0F .rpumk。3q3kvbhrx7xkumlbgjoobs8q ').角色('用户');} @覆盖公共无效配置(网络安全网站)引发异常{ } @覆盖受保护的void configure(HttpSecurity http)引发异常{ http.authorizeRequests().anyRequest().已验证()。和()。formLogin().loginProcessingUrl('/doLogin ').successHandler(new AuthenticationSuccessHandler(){ @在身份验证成功时覆盖公共void(HttpServletrequest请求,HttpServletResponse,身份验证身份验证)引发IOException,ServletException { resbean ok=resbean。' ok('登录成功!',验证。getprincipal());resp。SetContentType(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();out.write(新的对象映射器()。writeValueAsString(ok));出去。flush();出去。close();} }) .失败处理程序(新的authenticationfailure处理程序(){ @在authenticationfailure上覆盖公共void(HttpServletrequest请求,HttpServletResponse响应,AuthenticationException e)引发IOException,ServletException { RespBean错误=RespBean。错误(“”登录失败');resp。SetContentType(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();out.write(新的对象映射器()。writeValueAsString(错误));出去。flush();出去。close();} }) .登录页面('/login ').permitAll().和()。注销()。logoutUrl('/注销')。logoutSuccessHandler(新的logoutSuccessHandler(){ @覆盖公共void onLogoutSuccess(HttpServletrequest请求,HttpServletResponse,身份验证身份验证)引发IOException,ServletException { resbean ok=resbean。' ok('注销成功!');resp。SetContentType(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();out.write(新的对象映射器()。writeValueAsString(ok));出去。flush();出去。close();} }) .permitAll().和()。csrf().禁用()。异常处理()。accessdenieddhandler(new accessdenieddhandler(){ @ Override public void handler(HttpServletrequest req,HttpServletResponse,AccessDeniedException e)引发IOException,ServletException { RespBean错误=RespBean。错误(“”权限不足,访问失败');resp。SetStatus(403);resp。SetContentType(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();out.write(新的对象映射器()。writeValueAsString(错误));出去。flush();出去。close();} });}}这里的配置虽然有点长,但是很基础,配置含义也比较清晰,首先提供BCryptPasswordEncoder作为密码代码,可以实现对密码的自动加密加盐,非常方便,然后提供了一个名为张三的用户,密码是123,角色是用户,最后配置登录逻辑,所有的请求都需要登录后才能访问,登录接口是/doLogin,用户名的键是用户名,密码的键是密码,同时配置登录成功、登录失败以及注销成功、权限不足时都给用户返回数据提示,另外,这里虽然配置了登录页面为/登录,实际上这不是一个页面,而是一段JSON,在逻辑控制器中提供该接口,如下:
@ rest controller @ responsebody public class LoginController { @ GetMapping('/log in ')public RespBean log in(){ return RespBean。错误(“”尚未登录,请登录');} @ GetMapping("/hello ")公共字符串hello(){ 0返回“你好”;}}这里/login只是一个数据提示,而不是页面,/你好则是一个测试接口。
好的,做完上述步骤就可以开始测试了,运行回弹项目,访问/你好接口,结果如下:
此时先调用登录接口进行登录,如下:
登录成功后,再去访问/你好接口就可以成功访问了。
使用数据登录
上面演示的是一种原始的登录方案,如果想将用户名密码通过数据的方式进行传递,则需要自定义相关过滤器,通过分析源码我们发现,默认的用户名密码提取在usernamepassworauthenticationfilter过滤器中,部分源码如下:
公共类usernamepassword authenticationfilter扩展了AbstractAuthenticationProcessingFilter { public static final String SPRING _ SECURITY _ FORM _ USERNAME _ KEY=' USERNAME ';公共静态最终字符串SPRING _ SECURITY _ FORM _ PASSWORD _ KEY=' PASSWORD ';私有字符串usernameParameter=SPRING _ SECURITY _ FORM _ USERNAME _ KEY;私有字符串密码参数=SPRING _ SECURITY _ FORM _ PASSWORD _ KEY;private boolean PostOnly=true public usernamepassworauthenticationfilter(){ super(new antpathRequestMatcher('/log in ',' POST '));}公共身份验证尝试身份验证(HttpServletRequest请求,HttpServletResponse响应)引发AuthenticationException { if(PostOnly!request.getMethod().等于(' POST '){ 0抛出新的身份验证服务异常('身份验证方法不支持的身份验证方法请求。getmethod());}字符串用户名=获取用户名(请求);字符串密码=获取密码(请求);if(username==null){ username=' ';} if(password==null){ password=' ';}用户名=用户名。trim();usernamepassword authenticationtoken authRequest=new usernamepassword authenticationtoken(用户名、密码);//允许子类设置细节属性setDetails(请求,authRequest);返回this.getAuthenticationManager().验证(authRequest);}受保护的字符串获取密码(HttpServletRequest请求){退货请求。getParameter(password Parameter);}受保护的字符串获取用户名(HttpServletRequest请求){退货请求。GetParameter(usernameParameter);} //.//.}从这里可以看到,默认的用户名/密码提取就是通过请求中的参数名来提取的,如果想使用数据传递用户名密码,只需要将这个过滤器替换掉即可,自定义过滤器如下:
公共类CustomAuthenticationFilter扩展了用户名密码身份验证过滤器{ @覆盖公共身份验证尝试身份验证(HttpServletRequest请求,HttpServletResponse响应)引发AuthenticationException { if(请求。getcontenttype().等于(媒体类型.APPLICATION _ JSON _ UTF8 _ VALUE)| |请求。GetContentType().等于(媒体类型.APPLICATION _ JSON _ VALUE)){对象映射器映射器=新对象映射器();usernamepassworauthenticationtoken authRequest=null;try(InputStream is=request。getinputstream()){ MapString,String authenticationBean=mapper。readvalue(is,map。类);authRequest=new usernamepassword authenticationtoken(authenticationbean . get('用户名)、authenticationbean。' get('密码'));} catch(IOexception e){ e . print stack trace();authRequest=new usernamepassworauthenticationtoken(“,”);}最后{ setDetails(request,authRequest);返回this.getAuthenticationManager().验证(authRequest);} } else { return super。尝试验证(请求,响应);} }}这里只是将用户名/密码的获取方案重新修正下,改为了从数据中获取用户名密码,然后在安全性配置中作出如下修改:
@ overrided protected void configure(HttpSecurity Http)引发异常{ http.authorizeRequests().anyRequest().已验证()。和()。formLogin().和()。csrf().disable();http。addfilterat(customAuthenticationFilter()、usernamepassword authenticationfilter。类);} @ bean customAuthenticationFilter customAuthenticationFilter()引发异常{ customAuthenticationFilter filter=new customAuthenticationFilter();过滤器。setauthenticationsuccesshandler(new AuthenticationSuccessHandler(){ @在身份验证成功时覆盖公共void(httpersvletrequest请求,HttpServletResponse,身份验证身份验证)引发IOException,ServletException { resp。setcontenttype(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();RespBean respBean=RespBean.ok('登录成功!');out.write(新的对象映射器()。writeValueAsString(resbean));出去。flush();出去。close();} });过滤器。setauthenticationfailure处理程序(新的authenticationfailure处理程序(){ @在authenticationfailure时覆盖公共void失败(HttpServletRequest请求,HttpServletResponse,AuthenticationException e)引发IOException,ServletException { resp。setcontenttype(' application/JSON;charset=utf-8 ');PrintWriter out=resp。getwriter();resp bean resp bean=resp bean。错误(“”登录失败!');out.write(新的对象映射器()。writeValueAsString(resbean));出去。flush();出去。close();} });过滤器。setauthenticationmanager(authenticationManagerBean());返回过滤器;}将自定义的CustomAuthenticationFilter类加入进来即可,接下来就可以使用数据进行登录了,如下:
好了,本文就先介绍到这里,有问题欢迎留言讨论。希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:使用JSON格式数据的SpringSecurity登录方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。