Spring整合SpringSecurity(一)
- 创建项目
- 创建maven工程
- Spring容器注解配置
- Servlet Context注解配置
- 加载 Spring容器
- 认证
- 认证页面
- 安全配置
- Spring Security初始化
- 默认根路径请求
- 认证成功页面
- 测试
- 登录测试
- 退出
- 授权
- HttpSecurity
创建项目
代码远程地址:https://github.com/zysheep/spring-security.git
创建maven工程
项目结构:
添加pom依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.4.5</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.4.5</version>
</dependency>
</dependencies>
Spring容器注解配置
相当于配置文件application-context.xml
@Configuration
@ComponentScan(basePackages = "cn.zysheep",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class ApplicationConfig {
//在此配置除了Controller的其它bean,比如:数据库链接池、事务管理器、业务bean等。
}
Servlet Context注解配置
相当于spring- mvc.xml配置文件
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "cn.zysheep",
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class WebConfig implements WebMvcConfigurer {
// 配置视图解析器
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/views/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/","/login");
}
}
加载 Spring容器
相当于web.xml配置
public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class, WebSecurityConfig.class}; //指定spring容器
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class}; // 指定servletConfig即springmvc配置
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
认证
认证页面
springSecurity默认提供认证页面,不需要额外开发。
安全配置
spring security
提供了用户名密码登录、退出、会话管理等认证功能,只需要配置即可使用。
在config包下定义WebSecurityConfig,安全配置的内容包括:用户信息、密码编码器、安全拦截机制。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager detailsManager = new InMemoryUserDetailsManager();
detailsManager.createUser(User.withUsername("zhangsan").password("123").authorities("save","update").build());
detailsManager.createUser(User.withUsername("lisi").password("456").authorities("save").build());
return detailsManager;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
//配置授权服务,即安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.successForwardUrl("/user/login-success");
}
}
在userDetailsService()方法中,我们返回了一个UserDetailsService给spring容器,Spring Security会使用它来 获取用户信息。我们暂时使用InMemoryUserDetailsManager实现类,并在其中分别创建了zhangsan、lisi两个用 户,并设置密码和权限
而在configure()
中,我们通过HttpSecurity设置了安全拦截规则,其中包含了以下内容:
- 关闭csrf
- url匹配/user/**的资源,经过认证后才能访问。
- 其他url完全开放。
- 支持form表单认证,认证成功后转向/login-success。
加载 WebSecurityConfig
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class, WebSecurityConfig.class}; //指定spring容器,加载WebSecurityConfig
}
Spring Security初始化
public class SpringSecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
默认根路径请求
在WebConfig.java中添加默认请求根路径跳转到/login,此url为spring security提供:
//默认Url根路径跳转到/login,此url为spring security提供
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/","/login");
}
认证成功页面
在安全配置中,认证成功将跳转到/login-success,还可以配置登录页面和登录请求,认证失败请求
//配置授权服务,即安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.successForwardUrl("/user/login-success");
}
spring security支持form表单认证,认证成功后转向/login-success。
在LoginController中定义/login-success:
@Controller
@RequestMapping("/user")
public class LoginController {
@PostMapping("/login-success")
public String loginSuccess() {
//跳转到success页面
return "success";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功页面</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
测试
配置Tomcat,启动项目
页面会根据WebConfig中addViewControllers配置规则,跳转至/login,/login是spring Security提供的默认登录页面。
登录测试
输入错误的用户名、密码
http://localhost:8080/login?error
时spring security默认为我们提供的错误认证请求
输入正确的用户名、密码,登录成功
spring security内部转发到了/user/login-success
请求,我们自定义了这请求响应一个视图页面sucess.jsp
退出
请求/logout
退出
/logout
请求是SpringSecurity为我们提供的,退出 后再访问资源自动跳转到登录页面
授权
实现授权需要对用户的访问进行拦截校验,校验用户的权限是否可以操作指定的资源,Spring Security默认提供授 权实现方法。
LoginController
添加资源请求
@Controller
@RequestMapping("/user")
public class LoginController {
@PostMapping("/login-success")
public String loginSuccess() {
return "success";
}
@GetMapping("/save")
@ResponseBody
public String saveUser() {
return "save resources";
}
@GetMapping("/update")
@ResponseBody
public String updateUser() {
return "update resources";
}
@GetMapping("/delete")
@ResponseBody
public String deleteUser() {
return "delete resources";
}
@GetMapping("/get")
@ResponseBody
public String getUser() {
return "get resources";
}
}
在安全配置类WebSecurityConfig.java
中配置授权规则:
.antMatchers("/user/save").hasAuthority("save")
.antMatchers("/user/update").hasAuthority("update")
.antMatchers("/user/save").hasAuthority("save")
表示:访问/user/save资源的 url需要拥有save权限。
.antMatchers("/user/update").hasAuthority("update")
表示:访问/user/save资源的 url需要拥有update权限。
完整的WebSecurityConfig方法如下:
//配置授权服务,即安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user/save").hasAuthority("save")
.antMatchers("/user/update").hasAuthority("update")
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin() // 支持form表单验证
.successForwardUrl("/user/login-success"); // 自定义登录成功请求
}
测试:
- 先使用内存用户,登录成功
- 内存用户zhansan具有save和update访问权限,lisi具有save权限
- 访问/user/save和/user/update,有权限时则正常访问,否则返回403(拒绝访问)
- zhansan和lisi都可以访问/user/get和/user/delete资源,spring security对所有资源进行认证,认证用户即成功登录用户,/user/get和/user/delete都允许认证用户访问
HttpSecurity
HttpSecurity配置列表:
方法 | 说明 |
openidLogin() | 用于基于 OpenId 的验证 |
headers() | 将安全标头添加到响应 |
cors() | 配置跨域资源共享( CORS ) |
sessionManagement() | 允许配置会话管理 |
portMapper() | 允许配置一个PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的对象使用 PortMapper 从 HTTP 重定 向到 HTTPS 或者从 HTTPS 重定向到 HTTP。默认情况下,Spring Security使用一个PortMapperImpl映射 HTTP 端口8080到 HTTPS 端口 8443,HTTP 端口80到 HTTPS 端口443 |
jee() | 配置基于容器的预认证。 在这种情况下,认证由Servlet容器管理 |
x509() | 配置基于x509的认证 |
rememberMe | 允许配置“记住我”的验证 |
authorizeRequests() | 允许基于使用HttpServletRequest限制访问 |
requestCache() | 允许配置请求缓存 exceptionHandling() 允许配置错误处理 |
securityContext() | 在HttpServletRequests之间的SecurityContextHolder上设置SecurityContext的管理。 当使用WebSecurityConfigurerAdapter时,这将 自动应用 |
servletApi() | 将HttpServletRequest方法与在其上找到的值集成到SecurityContext中。 当使用WebSecurityConfigurerAdapter时,这将自动应用 |
csrf() | 添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用 |
logout() | 添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效来 清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success” |
anonymous() | 允许配置匿名用户的表示方法。 当与WebSecurityConfigurerAdapter结合使用时,这将自动应用。 默认情况下,匿名用户将使用 org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 “ROLE_ANONYMOUS” |
formLogin() | 指定支持基于表单的身份验证。如果未指定FormLoginConfigurer#loginPage(String),则将生成默认登录页面 |
oauth2Login() | 根据外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份验证 |
requiresChannel() | 配置通道安全。为了使该配置有用,必须提供至少一个到所需信道的映射 |
httpBasic() | 配置 Http Basic 验证 |
addFilterAt() | 在指定的Filter类的位置添加过滤器 |