Java Spring Security使用详解
什么是Spring Security?
Spring Security是Spring框架中一个强大的安全管理框架。它提供了一个全面而灵活的安全管理机制,可以让你轻松地管理应用程序中的身份验证、授权和其他安全相关的一切。
Spring Security 的核心概念
Authentication(认证)
Authentication(认证)是指验证用户是否是合法用户的过程。常用的认证方式有用户名密码验证、证书认证、Token认证、OpenID认证等。Authentication(认证)完成之后,系统将会给这个用户颁发一个唯一的授权Token,也就是以后访问时的凭证。
Authorization(授权)
Authorization(授权)是指验证某个已认证用户是否有权进行某个操作或者访问某个资源的过程。常用的授权方式有:基本授权、角色授权、资源授权和基于表达式的授权等。
FilterChain(过滤器链)
FilterChain是指一系列过滤器的集合。在Spring Security中,FilterChain主要是由一些过滤器和Spring Security的过滤器链实现的。整个过滤器链起到的作用类似于Servlet Filter,依次对请求进行预处理和处理,并且可以决定是否将请求继续交给下一个过滤器处理。
SecurityContext(安全上下文)
SecurityContext是指当前用户的安全上下文环境,是一个容器,主要存储了当前用户的身份验证信息及授权信息等。
Spring Security 集成步骤
-
添加Spring Security依赖
xml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.5.0</version>
</dependency> -
配置Spring Security
配置文件参考代码:
``` java
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/", "/home/**","/hello","/css/**","/js/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
```
这里的配置代码示例中,我们禁用了跨站点请求伪造(CSRF)保护,允许所有用户访问根页(/)及其子集(/home)和静态资源(/css/和/js/),限制只有角色为ADMIN的用户才能访问/admin路径下的页面,而其他请求需要进行身份认证,最后配置默认的登录页面为/login,退出功能为默认。
- 自定义UserDetailsService
UserDetailsService是Spring Security中的一个核心接口,提供了从数据源中读取用户信息的方法。我们需要自定义实现该接口中的loadUserByUsername方法,并将其注入到Spring Security中。
实现代码参考:
``` java
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private IUserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByName(username);
if (user == null) {
throw new UsernameNotFoundException("用户名不存在:" + username);
}
List<GrantedAuthority> authorities = new ArrayList<>();
if (user.getRole() != null) {
authorities.add(new SimpleGrantedAuthority(user.getRole().getName()));
}
return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(), authorities);
}
}
```
在该自定义的UserDetailsService实现代码中,我们查询数据库中的用户信息和角色信息,并通过SimpleGrantedAuthority创建GrantedAuthority列表,最后创建Spring Security中内置的User对象返回。
-
配置Spring Security 对静态资源的访问权限
静态资源是指一些HTML、CSS、JS等文件,这些文件不需要通过Spring MVC来进行响应,而是直接由Web服务器进行响应的。当我们使用Spring Security时,需要对这些静态资源进行访问控制。
注册对静态资源的安全过滤器:
``` java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowired private CustomResourceSecurityInterceptor customResourceSecurityInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customResourceSecurityInterceptor) .addPathPatterns("/css/**", "/js/**"); }
}
```注册安全拦截器:
``` java
@Component
public class CustomResourceSecurityInterceptor extends HandlerInterceptorAdapter {@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { boolean isAllow = false; if (request.getRequestURI().startsWith("/css/") || request.getRequestURI().startsWith("/js/")) { isAllow = true; } if (!isAllow) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } return isAllow; }
}
```所有的静态资源都保存在了Web项目的根目录下的/css/和/js/目录下面,根据这样一个规则,我们便可以通过request.getReuqestURI()判断出来该请求是不是静态资源,从而进行拦截处理。我们可以根据自己实际的应用场景,对相关代码进行调整和完善。
示例1:基于HTTP Basic认证的实现
HTTP Basic认证是基于用户名和密码进行简单的身份验证。
示例代码:
@EnableWebSecurity
public class HttpBasicSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/hello").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("password")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("password")).roles("ADMIN");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
在这里,我们加入了两个用户(user和admin),并给了他们不同的角色。这里我们使用了BCryptPasswordEncoder加密算法对用户的密码进行了加密。而且我们定义了访问/hello路径的所有请求都需要经过身份验证才能访问。
示例2:基于表单登录认证的实现
表单登录认证是指用户在登录时输入用户名和密码进行身份验证。
示例代码:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class FormAuthenticationConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and().logout().permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
在这里,我们通过@EnableGlobalMethodSecurity(securedEnabled = true)开启了secured的注解支持。并且还添加了登录页面的路径为"/login",和退出的路径为"/logout"。
这两个示例代码展示了如何在Spring Security中实现基本认证方式和表单登录认证,两个示例有着显著的差别,但是目的都是达到同一个目标:安全控制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java SpringSecurity使用详解 - Python技术站