需求
- 导入依赖
- 配置
- 应用
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.6.1</version>
</dependency>
作用:
- 所有的http请求都需要认证
- 对不同的请求路径,执行不同的安全规则
- 通过登录页面来提示用户进行认证
- 认证过程是通过HTTP basic认证对话框实现的
- 提供多个用户,并且设置权限
配置spring security
基于内存的配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("lei")
.password("123456")
.authorities("ROLE_USER")
.and()
.withUser("liu")
.password("1233456")
.authorities("ROLE_USER");
}
}
在上面的代码中,通过inMemoryAuthentication()方法创建了两个用户,并且每个用户的权限都是ROLE_USER.
基于JDBC的用户存储
@Configuration
@EnableWebSecurity
public class SecurityConfigs {
@Resource
DataSource dataSource;
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username,password,enabled from Users" +
"where username = ?"
)
.authoritiesByUsernameQuery(
"select username,authority from UserAuthorities "+
"where username =?"
)
.passwordEncoder(new StandardPasswordEncoder("53cr3t"));
}
}
上述代码,配置了数据库,以及查询用户信息、解码的sql语句。
自定义用户认证
定义用户实体类
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements UserDetails {
private static final long serialVersionUID =1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String password;
private String fullname;
private String street;
private String city;
private String state;
private String zip;
private String phoneNumber;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
上述代码实现了UserDeatils接口,这样我们能够提供更多信息给框架,比如用户都被授予了哪些权限以及用户的账号是否可用。
创建用户持久层
@Repository
public interface UserDao extends CrudRepository<User,Long> {
User findByUsername(String username);
}
创建用户服务层
用户服务层·
@Service
public class UserRepositoryUserDetailsService implements UserDetailsService{
@Autowired
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) {
User user = userDao.findByUsername(username);
if (user!=null){
return user;
}
throw new UsernameNotFoundException("User"+username+"not found");
}
}
配置类
@Configuration
@EnableWebSecurity
public class SecurityConfigss extends WebSecurityConfigurerAdapter {
@Autowired
private UserRepositoryUserDetailsService userDetailsService;
@Bean
public PasswordEncoder encoder(){
return new StandardPasswordEncoder("53cr3t");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
}
保护请求
配置类
@Configuration
@EnableWebSecurity
public class SecurityConfigss extends WebSecurityConfigurerAdapter {
@Autowired
private UserRepositoryUserDetailsService userDetailsService;
@Bean
public PasswordEncoder encoder(){
return new StandardPasswordEncoder("53cr3t");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.antMatchers("/design","/orders")
.hasRole("ROLE_USER")
.antMatchers("/","/*")
.permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/design",true)
.and()
.logout()
.logoutSuccessUrl("/out")
.and()
.csrf()
.disable();
}
}
- antMatchers("/design","/orders") 添加url
- hasRole(“ROLE_USER”) 必须拥有ROLE_USER权限的才可以访问上面添加的url
- antMatchers("/","/*") 添加所有url
- .permitAll() 所有用户都可以访问的,但是基于前面的条件(必须拥有ROLE_USER权限的才可以访问("/design","/orders"))
- formLogin().loginPage("/login") 添加用户登录界面,也就是用户如果没有登录,会自动跳转到这个界面
- .defaultSuccessUrl("/design",true) 登录成功后,如果添加了true这个参数,则默认添加到这个界面。
- .logout().logoutSuccessUrl("/out") 退出后默认跳转的页面
- csrf() .disable(); 禁用csfr,容易造成“跨站请求伪造”。如果不禁用的情况下可以在前端中添加一个隐藏的token。
获取用户信息
@RestController
@RequestMapping("/get")
public class GetUserInfo {
@ResponseBody
@PostMapping
public User getUserInfo(Authentication authentication){
User user = (User) authentication.getPrincipal();
return user;
}
}