需要,基于RBAC的权限访问,采用SpringSecurity安全管理框架+SpringBoot+Mybatis数据库持久框架。
user用户名:ennabled,accountNonExpired,accountNonLocked,CredentialsNonExpired默认为1
role角色表:
permisson权限表:
user_role 用户-角色中间表:
role_permission色色-权限中间表:
permission表中初始数据,权限名为permTag
1.pom.xml,引入了jdbc,thymeleaf,security,web,mybatis,devtools,lombox,mysql
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-security
2.3.1.RELEASE
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.2
org.springframework.boot
spring-boot-devtools
runtime
true
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
2.application.properties
#数据库连接,暂时未使用数据库连接池
spring.datasource.url=jdbc:mysql://localhost:3306/yderp
spring.datasource.username=root
spring.datasource.password=a61322799
#开发期间不需要缓存模板
spring.thymeleaf.cache=false
3.资源文件,其中main.html为需要权限才能访问的页面
reg.html
login.html
index.html
this is Main page!
权限页面
注销
main.html
本页面需要权限访问
注销
4.实体类domain
//角色实现UserDetails接口实现用户的封装
@Data
public class User implements UserDetails {
private int id;
private String username;
private String realname;
private String password;
private LocalDate createDate;
private LocalDateTime lastLoginTime;
//账户是否不可用,数据库为1代表true,0代表false,默认为1
private boolean enabled;
//账户是否未过期
private boolean accountNonExpired;
//账户是否锁定
private boolean accountNonLocked;
//密码是否未过期
private boolean credentialsNonExpired;
//权限集合
private List authorities;
}
@Data
public class Role {
private int id;
private String roleName;
private String roleDesc;
}
@Data
public class Permission {
private int id;
private String permName;
//权限标志符,authorities集合的值
private String permTag;
}
5.数据库查询dao接口
@Mapper
@Component
public interface UserDao {
//用户名查询用户信息
@Select("select * from user where userName = #{userName}")
public User selectByUserName(String userName);
//用户名查询当前用户的权限信息
@Select("select permission.* FROM" +
" user u" +
" INNER JOIN user_role ON u.id = user_role.uid" +
" INNER JOIN role_permission on user_role.rid = role_permission.rid" +
" INNER JOIN permission on role_permission.pid = permission.id" +
" WHERE u.username = #{userName};")
public List findPermissionByUserName(String userName);
//注册用户
@Insert("insert into user values(default,#{user.username}," +
"#{user.realname},#{user.password},now(),now(),default,default,default,default)")
int insert(@Param("user") User user);
}
6.UserService
public interface UserService {
public int insert(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao =null;
@Override
public int insert(User user) {
return userDao.insert(user);
}
}
7.MyController注册
@Controller
public class MyController {
@Autowired
UserService userService = null;
//用户注册
@RequestMapping("/reg")
@ResponseBody
public String reg(User user){
System.out.println(user);
String pwd = user.getPassword();
//加密,springSecurity现在默认要强制加密
pwd = new BCryptPasswordEncoder().encode(pwd);
user.setPassword(pwd);
int insert = userService.insert(user);
if(insert > 0){
return "注册成功";
}
return "注册失败";
}
}
8.springMVC config配置
@Configuration
public class MyConfig implements WebMvcConfigurer {
//静态资源URI和位置映射
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
//视图映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/").setViewName("index");
registry.addViewController("/403").setViewName("403");
registry.addViewController("/main").setViewName("main");
}
}
9.权限不足逻辑跳转
@Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
//权限不足的页面导向
ErrorPage error403 = new ErrorPage(HttpStatus.FORBIDDEN,"/403");
registry.addErrorPages(error403);
}
}
10.UserDetailsService接口的实现
@Service
public class MyUserDetalisService implements UserDetailsService {
@Autowired
UserDao userDao = null;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询当前用户信息
User user = userDao.selectByUserName(username);
//查询当前用户权限
List list = userDao.findPermissionByUserName(username);
List authorities = new ArrayList<>();
/*
* 将getPermTag()构建一个GrantedAuthority接口实例对象,放于List中
* */
list.forEach(l ->{
authorities.add(new SimpleGrantedAuthority(l.getPermTag()));
});
//用户信息设置权限集合
user.setAuthorities(authorities);
return user;
}
}
11.springSecurity配置,重点
@EnableWebSecurity
public class MySecurity extends WebSecurityConfigurerAdapter {
@Autowired
MyUserDetalisService myUserDetalisService = null;
//http安全配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //所有请求拦截
.antMatchers("/static/**").permitAll() //放在所有拦截的前面放行不需要拦截的资源
.antMatchers("/login").permitAll() //放行登录
.antMatchers("/logout").permitAll() //放行注销
.antMatchers("/reg").permitAll() //放行注册
.antMatchers("/main").hasAnyAuthority("ROLE_PRODUCT_LIST")//此页需要权限
.anyRequest().authenticated() //除上所有拦截需要用户认证
.and()
.formLogin().loginPage("/login") //forlogin认证
.failureUrl("/login?error=true")//登陆错误页
.and()
.csrf().disable(); //关闭csrf校验
}
//认证管理器配置
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetalisService)
//查询时需要密码加密后和数据库做比较
.passwordEncoder(new BCryptPasswordEncoder());
}
}