java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot配置Spring Security

SpringBoot配置Spring Security的实现示例

作者:G皮T

本文主要介绍了SpringBoot配置Spring Security的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.继承 WebSecurityConfigurerAdapter

通过重写抽象接口 WebSecurityConfigurerAdapter,再加上注解 @EnableWebSecurity,可以实现 Web 的安全配置。

WebSecurityConfigurerAdapterConfig 模块一共有 3 个 builder(构造程序)。

配置安全,通常要重写以下方法:

// 通过 auth 对象的方法添加身份验证
protected void configure(AuthenticationManagerBuilder auth) throws Exception {}
// 通常用于设置忽略权限的静态资源
public void configure(WebSecurity web) throws Exception {}
// 通过 HTTP 对象的 authorizeRequests() 方法定义 URL 访问权限。默认为 formLogin() 提供一个简单的登录验证页面
protected void configure(HttpSecurity httpSecurity) throws Exception {}

2.配置自定义策略

配置安全需要继承 WebSecurityConfigurerAdapter,然后重写其方法,见以下代码:

package com.example.demo.config;
 
// 指定为配置类
@Configuration
// 指定为 Spring Security 配置类,如果是 WebFlux,则需要启用@EnableWebFluxSecurity 
@EnableWebSecurity
// 如果要启用方法安全设置,则开启此项。
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(WebSecurity web) throws Exception {
    //不拦截静态资源
    web.ignoring().antMatchers("/static/**");
  }
  
  @Bean
  public PasswordEncoder passwordEncoder() {
    // 使用 BCrypt 加密
    return new BCryptPasswordEncoder();
  }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception { 
  	http.formLogin()
  			.usernameParameter("uname").passwordParameter("pwd").loginPage("/admin/login").permitAll()
				.and()
			.authorizeRequests()
				.antMatchers("/admin/**").hasRole("ADMIN")
				// 除上面外的所有请求全部需要鉴权认证
				.anyRequest().authenticated();
    http.logout().permitAll();
    http.rememberMe().rememberMeParameter("rememberme");
    // 处理异常,拒绝访问就重定向到 403 页面 
    http.exceptionHandling().accessDeniedPage("/403");
    http.logout().logoutSuccessUrl("/");
    http.csrf().ignoringAntMatchers("/admin/upload");
  }
}
http
    .someConfigurer
        .<some feature of configurer>()
        .<some feature of configurer>()
        .and()
    .someOtherConfigurer
        .<some feature of someOtherConfigurer>()
        ...
        .and()
     ...

如果开启了 CSRF,则一定在验证页面加入以下代码以传递 token 值:

<head>
  <meta name="_csrf" th:content="${_csrf.token}"/>
  <!-- default header name is X-CSRF-TOKEN -->
  <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>

如果要提交表单,则需要在表单中添加以下代码以提交 token 值:

<input type="hidden" th:name="${_csrf.parameterName)" th:value="${_csrf.token)">
<input class="i-checks" type="checkbox" name="rememberme"/>  记住我

3.配置加密方式

默认的加密方式是 BCrypt。只要在安全配置类配置即可使用,见以下代码:

@Bean
public PasswordEncoder passwordEncoder() {
	// 使用 BCrypt 加密
  return new BCryptPasswordEncoder();
}

在业务代码中,可以用以下方式对密码迸行加密:

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encodePassword = encoder.encode(password);

3.1 BCrypt 加密

BCrypt 是一种基于哈希函数的加密算法,它使用一个 密码 和一个 盐值 作为输入,生成一个固定长度的 密码哈希值。这个哈希值在每次密码输入时都会重新生成,而且会随着盐值的改变而改变。BCrypt 的盐值是一个随机生成的字符串,与密码一起用于哈希函数中,使得相同的密码在每次加密时都会生成不同的哈希值。

在这里插入图片描述

BCrypt 的另一个重要特点是它使用了一个加密算法来混淆密码哈希值。这个加密算法使用一个密钥和一个初始化向量(IV)来加密密码和盐值。加密后的数据被存储在数据库中,用于后续的密码验证。

BCrypt 的加密过程可以分为以下几个步骤:

在这里插入图片描述

🚀 BCrypt 加密/匹配工具 - 在线密码哈希生成与匹配

在这里插入图片描述

4.自定义加密规则

除默认的加密规则,还可以自定义加密规则。具体见以下代码:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception ( 
	auth.userDetailsService(UserService()).passwordEncoder(new PasswordEncoder() { 
		@Override
		public String encode(CharSequence charSequence) {
			return MD5Util.encode((String) charSequence);
		}
		@Override
		public boolean matches(CharSequence charSequence, String s) {
			return s.equals(MD5Util.encode((String) charSequence));
		}
  });
}

5.配置多用户系统

一个完整的系统一般包含多种用户系统,比如 “后台管理系统 + 前端用户系统"。Spring Security 默认只提供一个用户系统,所以,需要通过配置以实现多用户系统。

比如,如果要构建一个前台会员系统,则可以通过以下步骤来实现。

5.1 构建 UserDetailsService 用户信息服务接口

构建前端用户 UserSecurityService 类,并继承 UserDetailsService。具体见以下代码:

public class UserSecurityService implements UserDetailsService {
	@Autowired
	private UserRepository userRepository;
	@Override
	public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
		User user = userRepository.findByName(name);
		if (user == null) {
			User mobileUser = userRepository.findByMobile(name);
			if (mobileUser == null) {
				User emailUser = userRepository .findByEmail(name);
				if (emailUser == null) {
					throw new UsernameNotFoundException("用户名,邮箱或手机号不存在!");
				} else {
					user = userRepository.findByEmail(name);
				}
			} else {
				user = userRepository.findByMobile(name);
			}
		} else if ("locked".equals(user.getStatus())) {
			//被锁定,无法登录
			throw new LockedException("用户被锁定”);
		}
		return user;
	}
}

5.2 进行安全配置

在继承 WebSecurityConfigurerAdapter 的 Spring Security 配置类中,配置 UserSecurityService 类。

@Bean
UserDetailsService UserService() {
	return new UserSecurityService();
}

如果要加入后台管理系统,则只需要重复上面步骤即可。

6.获取当前登录用户信息的几种方式

获取当前登录用户的信息,在权限开发过程中经常会遇到。而对新人来说,不太了解怎么获取,经常遇到获取不到或报错的问题。

所以,本节讲解如何在常用地方获取当前用户信息。

6.1 在 Thymeleaf 视图中获取

要 Thymeleaf 视图中获取用户信息,可以使用 Spring Security 的标签特性。

在 Thymeleaf 页面中引入 Thymeleaf 的 Spring Security 依赖,见以下代码:

<!DOCTYPE html>
<html lang="zh" xmlns:th=”http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
	<!-- 省略 -->
	<body>
		<!-- 匿名 -->
		<div sec:authorize="isAnonymous()">
			未登录,单击 <a th:href="@{/home/login}" rel="external nofollow" >登录</a>
		</div>
		<!-- 已登录 -->
		<div sec:authorize="isAuthenticated()">
			<p>已登录</p>
			<p>登录名: <span sec:authentication="name"></span></p>
			<p>角色: <span sec:authentication="principal.authorities"></span></p>
			<p>id: <span sec:authentication="principal.id"></span></p>
			<p>Username: <span sec:authentication="principal.username"></span></p>
		</div>
	</body>
</html>

这里要特别注意版本的对应。如果引入了 thymeleaf-extras-springsecurity 依赖依然获取不到信息,那么可能是 Thymeleaf 版本和 thymeleaf-extras-springsecurity 的版本不对。

请检查在 pom.xml 文件的两个依赖,见以下代码:

<dependency>
  <groupld>org.springframework.boot</groupld> 
  <artifactld>spring-boot-starter-thymeleaf</artifactld>
</dependency>

<dependency>
  <groupld>org.thymeleaf.extras</groupld>
  <artifactld>thymeleaf-extras-springsecurity5</artifactld>
</dependency>

6.2 在 Controller 中获取

在控制器中获取用户信息有 3 种方式,见下面的代码注释。

@GetMapping("userinfo")
public String getProduct(Principal principal, Authentication authentication, HttpServletRequest httpServletRequest) {
  /**
   * Description: 1.通过 Principal 参数获取
  */
  String username = principal.getName();
  /**
   * Description: 2.通过 Authentication 参数获取
   */
  String userName2 = authentication.getName();
  /**
   * Description: 3.通过 HttpServletRequest 获取
   */
  Principal httpServletRequestUserPrincipal = httpServletRequest.getUserPrincipal();
  String userName3 = httpServletRequestUserPrincipal.getName();
  return username;
}

6.3 在 Bean 中获取

在 Bean 中,可以通过以下代码获取:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
if (!(authentication instanceof AnonymousAuthenticationToken)) {
	String username = authentication.getName();
  return username;
}

在其他 Authentication 类也可以这样获取。比如在 UsernamePasswordAuthenticationToken 类中。

如果上面代码获取不到,并不是代码错误,则可能是因为以下原因造成的:

到此这篇关于SpringBoot配置Spring Security的实现示例的文章就介绍到这了,更多相关SpringBoot配置Spring Security内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

您可能感兴趣的文章:
阅读全文