一、前言
Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架。Spring Security提供了完整的安全性解决方案,它能够在Web请求级别和方法调用级别处理身份认证和授权。因为基于Spring框架,所以Spring Security充分利用了依赖注入(dependency injection,DI)和面向切面的技术。
二、Spring Security详情
2.1.实现
Spring Security从两个角度来解决安全性问题:使用Servlet规范中的Filter保护Web请求并限制URL级别的访问;使用Spring AOP保护方法调用——借助于对象代理和使用通知,能够确保只有具备适当权限的用户才能访问安全保护的方法。
对于Spring Security来说主要提供的两个安全服务是指:认证(Authentication)和 授权(Authorization);认证是用来确定当前用户,授权是判断一个用户是否有访问某个安全对象的权限。
2.2.Spring Security模块
下面常用的模块包括:配置(config)、核心(core)和Web是必须要的;标签库也是常用的模块。
Spring Security标签库支持的标签包括:
使用方式如下所示:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')">
</http>
2.3.Spring Security用户认证
Spring Security中提供了多种的用户认证策略,常用的认证策略包括(认证将在后面详细说明过程):
1.基于内存的用户存储(下面第一个Demo就是基于内存的用户存储)
2.基于数据库表进行认证(将在后面展示Demo)
3.基于LDAP进行用户认证(将在后面展示Demo)
三、Spring Security Demo
3.1.基于传统的XML实现
配置SpringSecurity(web.xml), DelegatingFilterProxy是Servlet Filter的代理类,通过这个类可以让Servlet Filter通过Spring来管理。它可以链接任意多个其他的过滤器,根据这些过滤器提供不同的安全特性.
<!-- SpringSecuity配置 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringSecurity具体配置(spring-security.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 静态资源不需要安全验证 -->
<http pattern="/resources/**" security="none"/>
<http auto-config="true" use-expressions="false">
<intercept-url pattern="/admin**" access="ROLE_ADMIN" />
<intercept-url pattern="/user**" access="ROLE_USER" />
<!-- HTTP基本认证
<http-basic/> -->
<!-- 通过form-login设置自定义的登陆界面
<form-login/> -->
<!-- 通过logout设置退出登陆地址等
<logout/> -->
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_ADMIN" />
<user name="wuxinhui" password="123456" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
在最小化配置中只需要配置<http>节点(对特定的http请求基于安全考虑进行配置)和<authentication-manager>认证管理器。其中http-basic认证是弹出Dialog框进行用户名密码输入而不是完整的页面。
最后就是需要准备相应的controller,如下所示:
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security");
model.addObject("message", "This is welcome page!");
model.setViewName("hello");
return model;
}
@SuppressWarnings("unused")
@RequestMapping(value = "/admin", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security");
model.addObject("message", "This is admin page!");
model.setViewName("admin");
return model;
}
@RequestMapping(value = "/user", method = RequestMethod.GET)
public ModelAndView userPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security");
model.addObject("message", "This is user page!");
model.setViewName("admin");
return model;
}
}
项目结构如下所示:
3.2.基于Java配置实现
主要是实现 WebSecurityConfigurerAdapter适配器的类,如下所示。当使用@EnableWebSecurity注解时,其实就可以使用Spring Security,这时Spring Security会生成一串密码(用户名默认是user),例如:Using generated security password: c6ef06a4-6b1a-4932-b834-87d3923c919b。和XML配置类似,Java配置也需要两个基本的配置:httpSecurity和AuthenticationManager。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throw