引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
应用安全
防止攻击
DDos、CSRF、XSS、SQL注入...
控制权限
登录的用户能干什么
用户登录系统以后要控制住用户的所有行为,防止越权
传输加密
https
X509
认证
OAuth2.0
JWT
RBAC权限模型
Role Based Access Controll
:基于角色的访问控制
一个网站可以有许多用户,每个用户可以有许多角色,每个角色可以关联许多权限
认证:用户登录
授权:给每个方法规定好权限,由权限框架否则判断调用者是否有指定权限
认证
配置类
package com.tlovo.security.config;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
@RequiredArgsConstructor
public class SecurityAppConfiguration {
private final ReactiveUserDetailsService userDetailsService;
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
// 1.定义哪些请求需要认证,哪些不需要
http.authorizeExchange(auth -> {
// 允许所有人访问匹配请求路径
// auth.pathMatchers("/**").permitAll();
// 允许访问所有静态资源
auth.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
// 剩下的都需要认证
auth.anyExchange().authenticated();
});
// 2.开启默认表单登录
http.formLogin();
// 3.安全控制
http.csrf(csrfSpec -> {
csrfSpec.disable();
});
// 4.配置 认证规则(数据库查询)
http.authenticationManager(new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService));
// 构建安全配置
return http.build();
}
}
用户信息服务
package com.tlovo.security.component;
import lombok.RequiredArgsConstructor;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
@RequiredArgsConstructor
public class UserDetailsService implements ReactiveUserDetailsService {
private final DatabaseClient databaseClient;
// 自定义如何按照用户名去数据库查询用户信息
@Override
public Mono<UserDetails> findByUsername(String username) {
return databaseClient.sql("select u.*,r.id rid,r.name,r.value,pm.id pid,pm.value pvalue,pm.description"
+ " from t_user u"
+ " left join t_user_role ur on ur.user_id=u.id"
+ " left join t_roles r on r.id=ur.role_id"
+ " left join t_role_perm rp on rp.role_id=r.id"
+ " left join t_perm pm on rp.perm_id=pm.id"
+ " where u.username=? limit 1")
.bind(0, username)
.fetch()
.one() // all
.map(map -> {
return User.builder()
.username(username)
.password(map.get("password").toString())
.authorities("download", "delete", "view") // 权限 - 应该从数据库获取
.roles("admin", "sale") // 身份 - 应该从数据库获取
.build();
});
}
}