spring spring-security
概述- 认证(你是谁,户/设备/系统
- 验证(你能干什么,也叫权限控制/授权,允许执行的操作)
- 基于Filter , Servlet, AOP实现身份认证和权限验证
入门案例
1、新建工程,导入依赖
org.springframework.bootspring-boot-starter-security
2、配置访问地址,启动测试,获得秘钥
登陆名:user
密码:查看日志
3、小结
使用AOP做了拦截,拦截后再访问的servlet
security相关配置
自定义用户名和密码
在Application.yml 中配置文件上的security的user和password
spring: security: user: name: admin password: admin
关闭验证
在启动类的注解中,排除安全验证,使用内存中的用户信息
使用内存中的账户
使用类WebSecurityConfigurerAdapter控制安全管理内容
- 自定义类继承WebSecurityConfigurerAdapter,声明是个配置类、开启WebSecurity
- 重写configure方法
- 在SpringSecurity_v5.0版本中,密码必须使用一个加密方式
- 构建一个方法创建一个BCrypt加密类,用于加密操作(BCrypt跨平台)
@Configuration @EnableWebSecurity public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 得到一个加密类, PasswordEncoder passwordEncoder = passwordEncoder(); auth.inMemoryAuthentication().withUser("zhangsan").password(passwordEncoder.encode("zhangsan")).roles(); auth.inMemoryAuthentication().withUser("lisi").password(passwordEncoder.encode("lisi")).roles(); auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("admin")).roles(); } // 构建一个方法创建一个加密类,放入容器中 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
使用数据库的账户
1、导入依赖
mysqlmysql-connector-java8.0.23org.springframework.bootspring-boot-starter-data-jpa2.4.5
2、封装对象,创建一个实体类,初始化数据 使用JPA连接数据库
3.1、创建一个实体类
package com.study.entity; import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity @Data public class UserInfo { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String username; private String password; private String role; }
3.2、创建一个dao
package com.study.dao; import com.study.entity.UserInfo; import org.springframework.data.jpa.repository.JpaRepository; public interface UserInfoDao extends JpaRepository{ UserInfo findByUsername(String name); }
3.3、创建service层的类 接口和实现类
package com.study.service; import com.study.entity.UserInfo; public interface UserInfoService { UserInfo findUserInfo(String username); }
package com.study.service.impl; import com.study.dao.UserInfoDao; import com.study.entity.UserInfo; import com.study.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserInfoServiceImpl implements UserInfoService { @Autowired UserInfoDao userInfoDao; public UserInfo findUserInfo(String username) { UserInfo userInfo = userInfoDao.findByUsername(username); return userInfo; } }
3.4、配置数据库连接信息
spring.datasource.url=jdbc:mysql://8.129.121.241:3306/springsecurity?serverTimezone=GMT%2B8&characterEncoding=utf8 spring.datasource.username=xxyy spring.datasource.password=xxYY11.. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #spring-data-jpa spring.jpa.generate-ddl=true spring.jpa.show-sql=true spring.jpa.database=mysql
3.5、初始化数据库数据
package com.study.init; import com.study.dao.UserInfoDao; import com.study.entity.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class JdbcInit { @Autowired private UserInfoDao userInfoDao; @PostConstruct public void init() { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); UserInfo userInfo = new UserInfo(); userInfo.setUsername("lisi"); userInfo.setPassword(passwordEncoder.encode("lisi")); userInfo.setRole("normal"); userInfoDao.save(userInfo); } }
3.6、查询数据库,构造一个User对象,用于框架中使用
package com.study.provider; import com.study.dao.UserInfoDao; import com.study.entity.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service public class MyUserDetailService implements UserDetailsService { @Autowired private UserInfoDao userInfoDao; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user=null; UserInfo userInfo=null; if(username!=null){ userInfo = userInfoDao.findByUsername(username); if (userInfo!=null){ Listlist=new ArrayList(); GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_"+userInfo.getRole()); list.add(authority); user=new User(userInfo.getUsername(),userInfo.getPassword(),list); } } return user; } }
4、编写配置类,将通过数据库得到的User对象,进行角色配置
package com.study.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } }
5、添加Controller,最后测试验证,注意将添加数据库信息的注解注释掉
package com.study.controller; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping(value = "/hello") public String hello() { return "hello spring-security"; } @RequestMapping(value = "/hellouser") @PreAuthorize(value = "hasAnyRole('ROLE_admin','ROLE_normal')") public String helloUser() { return "hello spring-security have normail Admin role"; } @RequestMapping(value = "/helloadmin") @PreAuthorize(value = "hasAnyRole('ROLE_admin')") public String helloAdmin() { return "hello spring-security have Admin role"; } }
踩坑
所有的权限都要加上 “ROLE_” 作为前缀
未完待续