spring security (二) spring security自定义登录

拦截请求

     对每个请求进行细粒度安全性控制的关键在于重载configure(HttpSecurity)方法。如下的代码片段展现了重载的configure(HttpSecurity)方法,它为不同的URL路径有选择地应用安全性:

http 
                .authorizeRequests()
                .antMatchers( "/spittles/me").authenticated()
                .antMatchers(HttpMethod.POST,"/test/index").hasAnyAuthority("ROLE_USER")

                .anyRequest().permitAll()

     configure()方法中得到的HttpSecurity对象可以在多个方面配置HTTP的安全性。在这里,我们首先调用authorizeRequests(),然后调用该方法所返回的对象的方法来配置请求级别的安全性细节。其中,第一次调用antMatchers()指定了对“/spitters/me”路径的请求需要进行认证。第二次调用antMatchers()更为具体,说明对“/spittles”路径的HTTP POST请求必须要经过认证。最后对anyRequests()的调用中,说明其他所有的请求都是允许的,不需要认证和任何的权限。

       antMatchers()方法中设定的路径支持Ant风格的通配符。在这里我们并没有这样使用,但是也可以使用通配符来指定路径,如下所示:

.antMatchers("/spitters/**").authenticated();

       除了路径选择,我们还通过authenticated()和permitAll()来定义该如何保护路径。authenticated()要求在执行该请求时,必须已经登录了应用。如果用户没有认证的话,Spring Security的Filter将会捕获该请求,并将用户重定向到应用的登录页面。同时,permitAll()方法允许请求没有任何的安全限制。

       除了authenticated()和permitAll()以外,还有其他的一些方法能够用来定义该如何保护请求。表描述了所有可用的方案。



       通过使用表中的方法,我们所配置的安全性能够不仅仅限于认证用户。例如,我们可以修改之前的configure()方法,要求用户不仅需要认证,还要具备ROLE_USER权限。

      我们可以将任意数量的antMatchers()、regexMatchers()和anyRequest()连接起来,以满足Web应用安全规则的需要。但是,我们需要知道,这些规则会按照给定的顺序发挥作用。所以,很重要的一点就是将最为具体的请求路径放在前面,而最不具体的路径(如anyRequest())放在最后面。如果不这样做的话,那不具体的路径配置将会覆盖掉更为具体的路径配置。

认证用户

     如果你使用程序清单9.1中最简单的Spring Security配置的话,那么就能无偿地得到一个登录页。实际上,在重写configure(HttpSecurity)之前,我们都能使用一个简单却功能完备的登录页。但是,一旦重写了configure(HttpSecurity)方法,就失去了这个简单的登录页面。

添加自定义的登录页

<html>
<head>
    <title>login</title>
</head>
<body>
<div id="login">
    <form id="loginForm" method="post" action="/login.do">
        <div class="login_item"><span>用户名:</span><input type="text" name="username"/></div>
        <div class="login_item"><span>密     码:</span><input type="password" name="password"/></div>
        <input id="remember_me" name="remember-me" type="checkbox"/>
        <label for="remember_me" class="inline">Remember me</label>
        <input name="submit" type="submit" value="Login"/>
        <security:csrfInput/>
    </form>
</div>
</body>

</html>

       需要注意的一个关键点是<form>提交到了什么地方。同时还需要注意username和password输入域,在你的登录页中,需要同样的输入域。最后,假设没有禁用CSRF的话,还需要保证包含了值为CSRFtoken的“_csrf”输入域。

       启用自定义的登录页面的配置如下:

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//关闭CSRF
                .formLogin()
                .loginPage("/login").loginProcessingUrl("/login.do")
                .failureUrl("/lError?error")
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/welcome")
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/spittles").authenticated()
                .antMatchers("/test/index").hasAnyAuthority("ROLE_USER")
                .anyRequest().permitAll();
    }

使用基于内存的认证

       因为我们的安全配置类扩展了WebSecurityConfigurerAdapter,因此配置用户存储的最简单方式就是重载configure()方法,并以AuthenticationManagerBuilder作为传入参数。AuthenticationManagerBuilder有多个方法可以用来配置Spring Security对认证的支持。通过inMemoryAuthentication()方法,我们可以启用、配置并任意填充基于内存的用户存储。

       下面SecurityConfig.java类重载了configure()方法,并使用两个用户来配置内存用户存储。

 //使用基于内存的认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //暂时使用基于内存的AuthenticationProvider
        auth.inMemoryAuthentication().withUser("user").password("pass").roles("USER").and()
                .withUser("admin").password("pass").authorities("ROLE_USER", "ROLE_ADMIN");

    }

       我们可以看到,configure()方法中的AuthenticationManagerBuilder使用构造者风格的接口来构建认证配置。通过简单地调用inMemoryAuthentication()就能启用内存用户存储。但是我们还需要有一些用户,否则的话,这和没有

用户并没有什么区别。

       因此,我们需要调用withUser()方法为内存用户存储添加新的用户,这个方法的参数是username。withUser()方法返回的是UserDetailsManagerConfigurer.UserDetailsBuilder,这个对象提供了多个进一步配置用户的方法,包括设置用户密码的password()方法以及为给定用户授予一个或多个角色权限的roles()方法。

      除了password()、roles()和and()方法以外,还有其他的几个方法可以用来配置内存用户存储中的用户信息。表描述了UserDetailsManagerConfigurer.UserDetailsBuilder对象所有可用的方法。


完整的SecurityConfig.java配置类如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    //使用基于内存的认证,spring 实战第九章
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //暂时使用基于内存的AuthenticationProvider
        auth.inMemoryAuthentication().withUser("user").password("pass").roles("USER").and()
                .withUser("admin").password("pass").authorities("ROLE_USER", "ROLE_ ADMIN");    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }

    /**
     * Spring Security 4.0之后,引入了CSRF,默认是开启。不得不说,CSRF和RESTful技术有冲突。
     * CSRF默认支持的方法: GET|HEAD|TRACE|OPTIONS,不支持POST。
     * authenticated()  要求在执行该请求时必须已经登录了应用,未登录会重定向到登录页面。
     * permitAll()    允许请求没有任何的安全限制。
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()//关闭CSRF
                .formLogin()
                .loginPage("/login").loginProcessingUrl("/login.do")
                .failureUrl("/lError?error")
                .usernameParameter("username")
                .passwordParameter("password")
                .defaultSuccessUrl("/welcome")
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/spittles").authenticated()
                .antMatchers("/test/index").hasAnyAuthority("ROLE_USER")
                .anyRequest().permitAll();

    }
}

welcome.jsp页面如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>Title</title>
</head>
<body>
<a href="/test/index">Spi</a>
</body>

</html>

运行结果及工程目录:


在没有登录时进入http://localhost:8080/test/index会跳转到登录页面。

源码地址:

https://download.csdn.net/download/u014572215/10412666https://download.csdn.net/download/u014572215/10412666 点击打开链接


猜你喜欢

转载自blog.csdn.net/u014572215/article/details/80306219