1.SpringBoot-Security技术

1.1 技术介绍

  1. 安全框架,权限控制的框架,包括认证功能、授权功能、加密功能、会话管理、缓存支持、记住登录信息等功能。

1.2 技术注意点

  • 使用了spring security 后,@controller注解不能写地址
  • @PreAuthorize注解一定要使用权限时才使用,如需要开放某接口时,则禁止使用,否则无法访问,并且排查异常麻烦,没有错误日志。

    1.5 demo的技术代码实现

    1.5.1 无数据库入门案例

    1.准备pom

    父工程准备
    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.2.2.RELEASE</version>
    5. <relativePath/> <!-- lookup parent from repository -->
    6. </parent>

引入其pom的子工程

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-devtools</artifactId>
  12. <scope>runtime</scope>
  13. <optional>true</optional>
  14. </dependency>
  15. <dependency>
  16. <groupId>org.projectlombok</groupId>
  17. <artifactId>lombok</artifactId>
  18. <version>1.18.10</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. <scope>test</scope>
  24. <exclusions>
  25. <exclusion>
  26. <groupId>org.junit.vintage</groupId>
  27. <artifactId>junit-vintage-engine</artifactId>
  28. </exclusion>
  29. </exclusions>
  30. </dependency>

2.准备application.yml

  1. server:
  2. port: 8080

3.准备启动项

  1. @SpringBootApplication
  2. public class SpringSecurityApplication {
  3. public static void main(String[] args){
  4. SpringApplication.run(SpringSecurityApplication.class,args);
  5. }
  6. }

启动main服务,测试其构建的springboot没有问题后,在进行下一步操作。

4.创建一个测试控制器

  1. @RestController
  2. public class HelloController {
  3. @GetMapping("/hello")
  4. public String hello(){
  5. return "hello spring security!";
  6. }
  7. }

5. 简单测试

访问 http://localhost:8080/hello 地址,默认spring security会访问自带的login登录页面,效果如下:
image.png

默认用户名:user,密码:在控制台打印了。

参考博文链接:https://www.cnblogs.com/xuweiweiwoaini/p/13890551.html

6. 添加自定义配置

作用:这个页面不符合自身需求,美观和功能需求都没有满足,我想要个注册按钮,记住密码,第三方登录,短信登录,邮件登录,验证码等等功能,这个默认的页面都无法满足我们的需求。这时spring security给了我们自定义页面的方案,并为我们提供了鉴权和授权的相应配置。

这时,需要引入两个东西,一个是相当于xml配置,设置一些我们想要的属性,该对象注入spring配置中心,进行授权验证服务。而我们还需要一个和本省程序联系的类,该对象进行和业务层调用联系,并在这里进行鉴权服务。

7 application.yml

设置一个默认的用户名和密码

  1. spring:
  2. security:
  3. user:
  4. name: admin
  5. password: 123456

配置类

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  4. private static final String USERNAME = "user";
  5. private static final String PASSWORD = "123456";
  6. /**
  7. * 密码加密算法
  8. *
  9. * @return
  10. */
  11. @Bean
  12. public BCryptPasswordEncoder bCryptPasswordEncoder() {
  13. return new BCryptPasswordEncoder();
  14. }
  15. /**
  16. * 授权验证服务(模拟没有用户详细信息实现类验证)
  17. *
  18. * @param auth
  19. * @throws Exception
  20. */
  21. @Override
  22. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  23. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  24. // 加密(SHA-256+随机盐+密钥)
  25. String password = encoder.encode(PASSWORD);
  26. // 验证管理员身份
  27. auth.inMemoryAuthentication().withUser(USERNAME).password(password).roles("ADMIN");
  28. }
  29. }

业务类

  1. @Service("userDetailsService")
  2. public class UserDetailsServiceImpl implements UserDetailsService {
  3. /**
  4. * 用户密码加密器(这里应该是注入dao或mapper来实现业务逻辑操作)
  5. */
  6. @Autowired
  7. private PasswordEncoder passwordEncoder;
  8. /**
  9. * 鉴权服务(模拟没有业务层鉴权)
  10. *
  11. * @param username 用户名
  12. * @return
  13. * @throws UsernameNotFoundException
  14. */
  15. @Override
  16. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  17. if (!ADMIN.equals(username)) {
  18. throw new UsernameNotFoundException("用户不存在或密码错误!");
  19. }
  20. // 这里的密码应该从数据库中取出
  21. String password = passwordEncoder.encode(PASSWORD);
  22. // 授予admin用户权限
  23. Collection<? extends GrantedAuthority> authorities =
  24. Stream.of(new SimpleGrantedAuthority("ADMIN")).collect(Collectors.toList());
  25. // 返回一个用户对象
  26. User user = new User(username, password, authorities);
  27. return user;
  28. }
  29. }

这时,你就可以进行测试,依然访问 http://localhost:8080 ,用户名:admin,密码:123456

不在是控制台生成的加密密码了。

并且 http://localhost:8080/hello 照样可以访问。

接着,将配置类和业务类建立连接,改造SpringSecurityConfig类

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Autowired
  5. @Qualifier(value = "userDetailsService")
  6. private UserDetailsServiceImpl userDetailsService;
  7. /**
  8. * 密码加密算法
  9. *
  10. * @return
  11. */
  12. @Bean
  13. public BCryptPasswordEncoder bCryptPasswordEncoder() {
  14. return new BCryptPasswordEncoder();
  15. }
  16. /**
  17. * 授权验证服务(通过业务层验证后返回用户详细信息)
  18. *
  19. * @param auth
  20. * @throws Exception
  21. */
  22. @Override
  23. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  24. auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
  25. }
  26. }

这时,又一次进行测试,再次访问 http://localhost:8080/hello , 输入用户名和密码后,成功访问!到这里入门案例结束。