资讯专栏INFORMATION COLUMN

spring security ajax登录及返回

ideaa / 1315人阅读

摘要:返回总共需要处理个地方,一个是异常的处理,需要兼容请求,一个是成功返回的处理,一个是失败返回的处理。这里就是拦截,获取提交的参数,然后交给去认证。之后就是走后续的,如果成功,则会进行相应的配置。动态配置权限笔记自定义

本文讲述一下如何自定义spring security的登录页,网上给的资料大多过时,而且是基于后端模板技术的,讲的不是太清晰,本文给出一个采用ajax的登录及返回的前后端分离方式。

ajax返回

总共需要处理3个地方,一个是异常的处理,需要兼容ajax请求,一个是成功返回的处理,一个是失败返回的处理。

ajax的异常处理
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        if(isAjaxRequest(request)){
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED,authException.getMessage());
        }else{
            response.sendRedirect("/login.html");
        }

    }

    public static boolean isAjaxRequest(HttpServletRequest request) {
        String ajaxFlag = request.getHeader("X-Requested-With");
        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
    }
}

这里我们自定义成功及失败的ajax返回,当然这里我们简单处理,只返回statusCode

AjaxAuthSuccessHandler
public class AjaxAuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_OK);
    }
}
AjaxAuthFailHandler
public class AjaxAuthFailHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed");
    }
}
security配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling().authenticationEntryPoint(new UnauthorizedEntryPoint())
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login","/css/**", "/js/**","/fonts/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .usernameParameter("name")
                .passwordParameter("password")
                .successHandler(new AjaxAuthSuccessHandler())
                .failureHandler(new AjaxAuthFailHandler())
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin").password("admin").roles("USER");
    }
}

这里有几个要注意的点:

permitAll

这里要添加前端资源路径,以及登陆表单请求的接口地址/login

loginPage

这里设置登录页面的地址,这里我们用静态页面,即static目录下的login.html

ajax配置

将authenticationEntryPoint,successHandler,failureHandler设置为上面自定义的ajax处理类

登录页面

就是一个纯粹的html页面,其中登录按钮的ajax请求如下:

$.ajax({
            url: "/login",
            type: "POST",
            data: "name="+name+"&password="+password,
            success: function (res, status) {
                window.location.href="/ok.html"
            },
            error: function (res, status) {
                dangerDialog(res.statusText);
            }
        });

这里是请求/login,也就是spring security会默认拦截的路径,不了解spring security的人可能会纳闷,我请求这个路径,但是工程里头没有定义/login的request mapping,不要紧么。下面来剖析一下。

spring security内置的各种filter:
Alias Filter Class Namespace Element or Attribute
CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channel
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter session-management/concurrency-control
HEADERS_FILTER HeaderWriterFilter http/headers
CSRF_FILTER CsrfFilter http/csrf
LOGOUT_FILTER LogoutFilter http/logout
X509_FILTER X509AuthenticationFilter http/x509
PRE_AUTH_FILTER AbstractPreAuthenticatedProcessingFilter Subclasses N/A
CAS_FILTER CasAuthenticationFilter N/A
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login
BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http/@servlet-api-provision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http/@jaas-api-provision
REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me
ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous
SESSION_MANAGEMENT_FILTER SessionManagementFilter session-management
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http
SWITCH_USER_FILTER SwitchUserFilter N/A

这里我们要关注的就是这个UsernamePasswordAuthenticationFilter,顾名思义,它是filter,在执行/login请求的时候拦截,因而是不需要工程里头去定义login的request mapping的。

UsernamePasswordAuthenticationFilter

spring-security-web-4.2.3.RELEASE-sources.jar!/org/springframework/security/web/authentication/UsernamePasswordAuthenticationFilter.java

public class UsernamePasswordAuthenticationFilter extends
        AbstractAuthenticationProcessingFilter {

public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        String username = obtainUsername(request);
        String password = obtainPassword(request);

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                username, password);

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }
    //......
}

这里就是拦截,获取login.html提交的参数,然后交给authenticationManager去认证。之后就是走后续的filter,如果成功,则会进行相应的session配置。

doc

spring security动态配置url权限

Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/11297.html

相关文章

  • spring security安全防护

    摘要:发现无效后,会返回一个的访问拒绝,不过可以通过配置类处理异常来定制行为。恶意用户可能提交一个有效的文件,并使用它执行攻击。默认是禁止进行嗅探的。 前言 xss攻击(跨站脚本攻击):攻击者在页面里插入恶意脚本代码,用户浏览该页面时,脚本代码就会执行,达到攻击者的目的。原理就是:攻击者对含有漏洞的服务器注入恶意代码,引诱用户浏览受到攻击的服务器,并打开相关页面,执行恶意代码。xss攻击方式...

    tuantuan 评论0 收藏0
  • Spring Security配置JSON登录

    摘要:准备工作基本的配置就不说了,网上一堆例子,只要弄到普通的表单登录和自定义就可以。是基于的,因此才能在基于前起作用。这样我们没有破坏原有的获取流程,还是可以重用父类原有的方法来处理表单登录。 spring security用了也有一段时间了,弄过异步和多数据源登录,也看过一点源码,最近弄rest,然后顺便搭oauth2,前端用json来登录,没想到spring security默认居然不...

    adam1q84 评论0 收藏0
  • Spring Security OAuth2 优雅的集成短信验证码登录第三方登录

    摘要:前言基于做微服务架构分布式系统时,作为认证的业内标准,也提供了全套的解决方案来支持在环境下使用,提供了开箱即用的组件。 前言 基于SpringCloud做微服务架构分布式系统时,OAuth2.0作为认证的业内标准,Spring Security OAuth2也提供了全套的解决方案来支持在Spring Cloud/Spring Boot环境下使用OAuth2.0,提供了开箱即用的组件。但...

    yck 评论0 收藏0
  • 不用 Spring Security 可否?试试这个小而美的安全框架

    摘要:写在前面在一款应用的整个生命周期,我们都会谈及该应用的数据安全问题。用户的合法性与数据的可见性是数据安全中非常重要的一部分。 写在前面 在一款应用的整个生命周期,我们都会谈及该应用的数据安全问题。用户的合法性与数据的可见性是数据安全中非常重要的一部分。但是,一方面,不同的应用对于数据的合法性和可见性要求的维度与粒度都有所区别;另一方面,以当前微服务、多服务的架构方式,如何共享Sessi...

    toddmark 评论0 收藏0
  • spring security登录、登出、认证异常返回值的自定义实现

    摘要:在整个学习过程中,我最关心的内容有号几点,其中一点是前后端分离的情况下如何不跳转页面而是返回需要的返回值。登录成功,不跳转页面,返回自定义返回值在官方文档第节,有这么一段描述要进一步控制目标,可以使用属性作为的替代。 在整个学习过程中,我最关心的内容有号几点,其中一点是【前后端分离的情况下如何不跳转页面而是返回需要的返回值】。下面就说一下学习结果,以xml配置位李。 登录成功,不跳转页...

    mushang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<