链接上一篇文章:spring学习之springSecurity(三)
1、基于角色或权限进行访问控制
hasAuthority 方法
如果当前的主体具有指定的权限,则返回 true,否则返回 false
修改配置类
添加一个控制器
@GetMapping("/find")
@ResponseBody
public String find(){
return "find";
}
给用户登录主体赋予权限
测试:
访问 findAll 进入登录页面
如果权限不正确,那么就会引导到对应的未授权页面
hasAnyAuthority 方法
如果当前的主体有任何提供的角色(给定的作为一个逗号分隔的字符串列表)的话,返回
true.
hasRole 方法
如果用户具备给定角色就允许访问,否则出现 403。
如果当前主体具有指定的角色,则返回 true。
底层源码:
给用户添加角色:
修改配置文件:
注意配置文件中不需要添加”ROLE_“,因为上述的底层代码会自动添加与之进行匹配。
hasAnyRole
表示用户具备任何一个条件都可以访问。
给用户添加角色:
修改配置文件:
基于数据库实现权限认证
添加实体类
@Data
public class Menu {
private Long id;
private String name;
private String url;
private Long parentId;
private String permission;
}
@Data
public class Role {
private Long id;
private String name;
}
编写接口与实现类
UserInfoMapper
/**
* @author: haijin
* @Date: 2022/11/07 23:59
*/
public interface UserInfoMapper {
/**
* 根据用户 Id 查询用户角色
* @param userId 用户id
* @return ignore
*/
List<Role> selectRoleByUserId(Long userId);
/**
* 根据用户 Id 查询菜单
* @param userId 用户id
* @return ignore
*/
List<Menu> selectMenuByUserId(Long userId);
}
上述接口需要进行多表管理查询:
需要在 resource/mapper 目录下自定义 UserInfoMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.haijin.dao.UserInfoMapper">
<!--根据用户 Id 查询角色信息-->
<select id="selectRoleByUserId" resultType="xyz.haijin.entity.Role">
SELECT r.id,r.name
FROM role r
INNER JOIN role_user ru ON
ru.rid=r.id where ru.uid=#{0}
</select>
<!--根据用户 Id 查询权限信息-->
<select id="selectMenuByUserId" resultType="xyz.haijin.entity.Menu">
SELECT m.id,m.name,m.url,m.parentid,m.permission
FROM menu m
INNER JOIN role_menu rm ON m.id=rm.mid
INNER JOIN role r ON r.id=rm.rid
INNER JOIN role_user ru ON r.id=ru.rid
WHERE ru.uid=#{0}
</select>
</mapper>
在配置文件中添加映射
在配置文件中 application.yml 添加
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
修改访问配置类
/**
* @author: haijin
* @Date: 2022/10/29 23:56
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsServiceImpl myUserDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
// 配置认证
http.formLogin()
// 配置哪个 url 为登录页面
.loginPage("/login.html")
// 设置哪个是登录的 url。
.loginProcessingUrl("/user/login")
//登录成功之后,跳转路径
.defaultSuccessUrl("/success.html").permitAll()
// 登录失败之后,跳转的页面
.failureUrl("/unauth.html")
.permitAll()
.and()
.authorizeRequests()
// 登录跳过页面
.antMatchers("/user/login")
// 指定 URL 无需保护。
.permitAll()
.antMatchers("/findAll")
// 是否有admin的权限
.hasRole("管理员")
.antMatchers("/find")
// 是否有role的权限
.hasAnyAuthority("menu:system")
// 其他请求
.anyRequest()
.authenticated(); //需要认证
// 关闭 csrf
http.csrf().disable();
}
// 注入 PasswordEncoder 类到 spring 容器中
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
使用管理员与非管理员进行测试
自定义 403 页面
http.exceptionHandling().accessDeniedPage("/unauth");
添加对应控制器
@GetMapping("/unauth")
public String accessDenyPage(){
return "unauth";
}
unauth.html
<body>
<h1>对不起,您没有访问权限!</h1>
</body>