SpringBoot 整合 SpringSecurity(权限控
2020-06-11 本文已影响0人
索性流年
来自蚂蚁课堂
链接:http://www.mayikt.com/
概述
- Spring Security是Spring提供的一个安全框架,提供认证和授权功能,为应用系统提供声明式的安全访问控制,减少了企业为系统安全控制的大量、重复代码。
SpringSecurity 应用场景
- 权限控制
- 身份认证
RBAC权限表设计
图片.pngpom 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
yml 配置
# 配置freemarker
spring:
freemarker:
# 设置模板后缀名
suffix: .ftl
# 设置文档类型
content-type: text/html
# 设置页面编码格式
charset: UTF-8
# 设置页面缓存
cache: false
# 设置ftl文件路径
template-loader-path:
- classpath:/templates
# 设置静态文件路径,js,css等
mvc:
static-path-pattern: /static/**
datasource:
name: test
url: jdbc:mysql://127.0.0.1:3306/mayikt_rbac
username: root
password: root
# druid 连接池
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
实现 WebSecurityConfigurerAdapter
@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MemberUserDetailsService memberUserDetailsService;
@Autowired
private PermissionMapper permissionMapper;
/**
* 添加授权账户
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// // 设置用户账号信息和权限
// auth.inMemoryAuthentication().withUser("mayikt_admin").password("mayikt")
// .authorities("addMember", "delMember", "updateMember", "showMember");
// // 如果mayikt_admin账户权限的情况 所有的接口都可以访问,如果mayikt_add 只能访问addMember
// auth.inMemoryAuthentication().withUser("mayikt_add").password("mayikt")
// .authorities("addMember");
auth.userDetailsService(memberUserDetailsService).passwordEncoder(new PasswordEncoder() {
/**
* 对密码MD5
* @param rawPassword
* @return
*/
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
/**
* rawPassword 用户输入的密码
* encodedPassword 数据库DB的密码
* @param rawPassword
* @param encodedPassword
* @return
*/
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String rawPass = MD5Util.encode((String) rawPassword);
boolean result = rawPass.equals(encodedPassword);
return result;
}
});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// //配置httpBasic Http协议认证
//// http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
// //配置httpBasic Http协议认证
// http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and()
// .formLogin();
// // 默认fromLog
List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
expressionInterceptUrlRegistry = http.authorizeRequests();
allPermission.forEach((permission) -> {
expressionInterceptUrlRegistry.antMatchers(permission.getUrl()).
hasAnyAuthority(permission.getPermTag());
});
expressionInterceptUrlRegistry.antMatchers("/login").permitAll()
.antMatchers("/**").fullyAuthenticated()
.and().formLogin().loginPage("/login").and().csrf().disable();
//.antMatchers("/addMember") 配置addMember请求权限 hasAnyAuthority("addMember")
}
/**
* There is no PasswordEncoder mapped for the id "null"
* 原因:升级为Security5.0以上密码支持多中加密方式,恢复以前模式
*
* @return
*/
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
Controller
@RestController
public class ErrorController {
@RequestMapping("/error/403")
public String error403() {
return "您当前访问的接口权限不足.";
}
}
@Controller
public class IndexController {
/**
* 跳转到首页
*
* @return
*/
@RequestMapping("/")
public String index() {
return "index";
}
@ResponseBody
@RequestMapping("/addMember")
public String addMember() {
return "新增用户";
}
@ResponseBody
@RequestMapping("/delMember")
public String delMember() {
return "删除用户";
}
@ResponseBody
@RequestMapping("/updateMember")
public String updateMember() {
return "修改用户";
}
@ResponseBody
@RequestMapping("/showMember")
public String showMember() {
return "查询用户";
}
}
自定义SpringBoot 错误异常
@Configuration
public class WebServerAutoConfiguration {
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
return factory;
}
}
实现 UserDetailsService
@Component
@Slf4j
public class MemberUserDetailsService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
/**
* loadUserByUserName
*
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1.根据该用户名称查询在数据库中是否存在
UserEntity userEntity = userMapper.findByUsername(username);
if (userEntity == null) {
return null;
}
// 2.查询对应的用户权限
List<PermissionEntity> listPermission = userMapper.findPermissionByUsername(username);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
listPermission.forEach(user -> {
authorities.add(new SimpleGrantedAuthority(user.getPermTag()));
});
log.info(">>>authorities:{}<<<", authorities);
// 3.将该权限添加到security
userEntity.setAuthorities(authorities);
return userEntity;
}
}
Dao
public interface UserMapper {
/**
* 根据用户名称查询
*
* @param userName
* @return
*/
@Select(" select * from sys_user where username = #{userName}")
UserEntity findByUsername(@Param("userName") String userName);
/**
* 查询用户的权限根据用户查询权限
*
* @param userName
* @return
*/
@Select(" select permission.* from sys_user user" + " inner join sys_user_role user_role"
+ " on user.id = user_role.user_id inner join "
+ "sys_role_permission role_permission on user_role.role_id = role_permission.role_id "
+ " inner join sys_permission permission on role_permission.perm_id = permission.id where user.username = #{userName};")
List<PermissionEntity> findPermissionByUsername(@Param("userName") String userName);
}
public interface PermissionMapper {
@Select(" select * from sys_permission ")
List<PermissionEntity> findAllPermission();
}
Entity
//权限表
@Data
public class PermissionEntity {
private Integer id;
// 权限名称
private String permName;
// 权限标识
private String permTag;
// 请求url
private String url;
}
// 角色信息表
@Data
public class RoleEntity {
private Integer id;
private String roleName;
private String roleDesc;
}
// 用户信息表
@Data
public class UserEntity implements UserDetails {
private Integer id;
private String username;
private String realname;
private String password;
private Date createDate;
private Date lastLoginTime;
private boolean enabled;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
// 用户所有权限
private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
}