spring security (一) 建立spring mvc工程

Spring Security简介

       Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架。Spring Security提供了完整的安全性解决方案,它能够在Web请求级别和方法调用级别处理身份认证和授权。因为基于Spring框架,所以Spring Security充分利用了依赖注入(dependency injection,DI)和面向切面的技术。

       最初,Spring Security被称为Acegi Security。Acegi是一个强大的安全框架,但是它存在一个严重的问题:那就是需要大量的XML配置。我不会向你介绍这种复杂配置的细节。总之一句话,典型的Acegi配置有几百行XML是很常见的。

理解Spring Security的模块

       不管你想使用Spring Security保护哪种类型的应用程序,第一件需要做的事就是将Spring Security模块添加到应用程序的类路径下。Spring Security 3.2分为11个模块


       应用程序的类路径下至少要包含Core和Configuration这两个模块。Spring Security经常被用于保护Web应用,所以我们还需要添加Web模块。同时我们还会用到Spring Security的JSP标签库,所以我们需要将这个模块也添加进来。

过滤Web请求

       Spring Security借助一系列Servlet Filter来提供各种安全性功能。你可能会想,这是否意味着我们需要在web.xml或WebApplicationInitializer中配置多个Filter呢?实际上,借助于Spring的小技巧,我们只需配置一个Filter就可以了。             DelegatingFilterProxy是一个特殊的Servlet Filter,它本身所做的工作并不多。只是将工作委托给一个javax.servlet.Filter实现类,这个实现类作为一个<bean>注册在Spring应用的上下文中


       如果你希望借助WebApplicationInitializer以Java的方式来配置Delegating-FilterProxy的话,那么我们所需要做的就是创建一个扩展的新类,在这里使用javaconfig创建类:SecurityWebInitializer.java

配置如下:

/**
 * 使用war注册springSecurityFilter
 */
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {
}

   只需要继承AbstractSecurityWebApplicationInitializer,AbstractSecurityWebApplicationInitializer实现了WebApplication-Initializer,因此Spring会发现它,并用它在Web容器中注册DelegatingFilterProxy。尽管我们可以重载它的appendFilters()或insertFilters()方法来注册自己选择的Filter,但是要注册DelegatingFilterProxy的话,我们并不需要重载任何方法。

       不管我们通过web.xml还是通过AbstractSecurityWebApplicationInitializer的子类来配置DelegatingFilterProxy,它都会拦截发往应用中的请求,并将请求委托给ID为springSecurityFilterChain bean。springSecurityFilterChain本身是另一个特殊的Filter,它也被称为FilterChainProxy。它可以链接任意一个或多个其他的Filter。Spring Security依赖一系列Servlet Filter来提供不同的安全特性。但是,你几乎不需要知道这些细节,因为你不需要显式声明springSecurityFilterChain以及它所链接在一起的其他Filter。当我们启用Web安全性的时候,会自动创建这些Filter。

编写简单的安全性配置

       在Spring Security的早期版本中(在其还被称为Acegi Security之时),为了在Web应用中启用简单的安全功能,我们需要编写上百行的XML配置。Spring Security 2.0提供了安全性相关的XML配置命名空间,让情况有了一些好转。

       Spring 3.2引入了新的Java配置方案,完全不再需要通过XML来配置安全性功能了。如下的程序清单展现了Spring Security最简单的Java配置。

       这里使用spring 的java配置:

@Configuration
@EnableWebSecurity                //启用web安全性

public class SecurityConfig extends WebSecurityConfigurerAdapter {

}

       顾名思义,@EnableWebSecurity注解将会启用Web安全功能。但它本身并没有什么用处,Spring Security必须配置在一个实现了WebSecurityConfigurer的bean中,或者(简单起见)扩展WebSecurityConfigurerAdapter。在Spring应用上下文中,任何实现了WebSecurityConfigurer的bean都可以用来配置SpringSecurity,但是最为简单的方式还是像程序清单那样扩展WebSecurityConfigurer Adapter类。

       @EnableWebSecurity可以启用任意Web应用的安全性功能,不过,如果你的应用碰巧是使用Spring MVC开发的,那么就应该考虑使用@EnableWebMvcSecurity替代它。

       看起来似乎并没有做太多的事情,但程序清单中的配置类会给应用产生很大的影响。其中任何一种配置都会将应用严格锁定,导致没有人能够进入该系统了!

       尽管不是严格要求的,但我们可能希望指定Web安全的细节,这要通过重载WebSecurityConfigurerAdapter中的一个或多个方法来实现。我们可以通过重载WebSecurityConfigurerAdapter的三个configure()方法来配置Web安全性,这个过程中会使用传递进来的参数设置行为。表描述了这三个方法。


       让我们重新看一下程序清单,可以看到它没有重写上述三个configure()方法中的任何一个,这就说明了为什么应用现在是被锁定的。尽管对于我们的需求来讲默认的Filter链是不错的,但是默认的configure(HttpSecurity)实际上等同于如下所示:

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin().and().httpBasic();

    }

      这个简单的默认配置指定了该如何保护HTTP请求,以及客户端认证用户的方案。通过调用authorizeRequests()和anyRequest().authenticated()就会要求所有进入应用的HTTP请求都要进行认证。它也配置Spring Security支持基于表单的登

录以及HTTP Basic方式的认证。

       同时,因为我们没有重载configure(AuthenticationManagerBuilder)方法,所以没有用户存储支撑认证过程。没有用户存储,实际上就等于没有用户。所以,在这里所有的请求都需要认证,但是没有人能够登录成功。

       为了让Spring Security满足我们应用的需求,还需要再添加一点配置。具体来讲,我们需要:

1.配置用户存储;

2.指定哪些请求需要认证,哪些请求不需要认证,以及所需要的权限

3.提供一个自定义的登录页面,替代原来简单的默认登录页。

       除了Spring Security的这些功能,我们可能还希望基于安全限制,有选择性地在Web视图上显示特定的内容。但首先,我们看一下如何在认证的过程中配置访问用户数据的服务。

使用基于内存的用户存储

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

@Override

 protected void configure(AuthenticationManagerBuilder auth)throws Exception{

        auth.inMemoryAuthentication().withUser("user")//启用内存用户存储
                .password("password").roles("USER").and()
                .withUser("admin").password("password") .roles("USER","ADMIN");
    }

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

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

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

       需要注意的是,roles()方法是authorities()方法的简写形式。roles()方法所给定的值都会添加一个“ROLE_”前缀,并将其作为权限授予给用户。实际上,如下的用户配置与程序清单是等价的:


       下面使用idea把上面所讲的内容实现起来:

       本文使用spring 版本是4.3.3,spring security版本是4.2.3,ide是idea2016,数据库是sqlserver2008。

       在idea中使用mave建立建立web工程。建好后的工程目录如下:

        这个就能使用tomcat运行了,运行结果只有一个hello world的页面,如下图:


配置DispatcherServlet

       DispatcherServlet是Spring MVC的核心。在这里请求会第一次接触到框架,它要负责将请求路由到其他的组件之中。按照传统的方式,像DispatcherServlet这样的Servlet会配置在web.xml文件中,这个文件会放到应用的WAR包里面。当然,这是配置DispatcherServlet的方法之一。但是,借助于Servlet 3规范和Spring 3.1的功能增强,这种方式已经不是唯一的方案了。

       我们会使用Java将DispatcherServlet配置在Servlet容器中,而不会再使用web.xml文件。如下的程序清单展示了所需的Java类。

        在config 目录下创建WebInitializer.java类继承AbstractAnnotationConfigDispatcherServletInitializer类

/**
 * Created by IBM on 2018/5/14.
 */
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    //
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

          WebConfig.java类 启用webmvc,配置jsp视图解析器来指定视图所在的位置,配置静态资源的处理

WebConfig@Configuration
@EnableWebMvc//启用SpringMVC
@ComponentScan("com.web.controller")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();//配置jsp视图解析器
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
//        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        return resolver;
    }

    //配置静态资源的处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }


}

         RootConfig.java类指定扫描的包和数据源类

@Configuration
@Import(DataConfig.class)
@ComponentScan(basePackages={"com"},
    excludeFilters={
//        @Filter(type= FilterType.CUSTOM, value=WebPackage.class)
        @Filter(type= FilterType.ANNOTATION, value=EnableWebMvc.class)
    })
public class RootConfig {
 /* public static class WebPackage extends RegexPatternTypeFilter {
    public WebPackage() {
      super(Pattern.compile("com\\.web"));
    }    
  }*/
}

        DataConfig.java类配置数据源,这里配置了两个但是使用的是datasource(),只要在sqlserver2008中建立一个数据库:db_SpringSecurity就不会报错。

@Configuration
public class DataConfig {

    @Bean
    public DataSource dataSource1(){
        BasicDataSource ds=new BasicDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
    @Bean
    public DataSource dataSource(){
        BasicDataSource ds=new BasicDataSource();
        ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        ds.setUrl("jdbc:sqlserver://localhost:1433;DatabaseName=db_SpringSecurity;SelectMethod=Cursor");
        ds.setUsername("sa");
        ds.setPassword("sa123");
        return ds;
    }

    @Bean
    public JdbcOperations jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

         建立控制器HomeController.java和视图home.java

@Configuration
@Controller//声明为一个控制器
@RequestMapping({"/home","/"})
@Component
public class HomeController {
    @RequestMapping(method = GET)//处理对“/”的GET请求。请求这个视图:http://localhost:8080/home
    public String home(){
        return "home";//视图名为home
    }
}

         这样spring mvc的配置就完成了。

         运行结果和工程目录如下:


下一篇配置spring security

猜你喜欢

转载自blog.csdn.net/u014572215/article/details/80283990
今日推荐