需要,基于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
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>2.application.properties
#数据库连接,暂时未使用数据库连接池
spring.datasource.url=jdbc:mysql://localhost:3306/yderp
spring.datasource.username=root
spring.datasource.password=a61322799
#开发期间不需要缓存模板
spring.thymeleaf.cache=false3.资源文件,其中main.html为需要权限才能访问的页面

reg.html
<form action="/reg" method="post">
用户名<input type="text" name="username"/> <br/>
用户名<input type="text" name="realname"/> <br/>
密码 <input type="password" name="password"/><br/>
<input type="submit" value="注册">
</form>login.html
<!--name值:必须为username password-->
<form method="post" action="/login">
用户名:<input type="text" name="username">
密码<input type="text" name="password">
<input type="submit" value="登录">
</form>
<!-- MySecurity类中 .failureUrl("/login?error=true")-->
<label style="color: red" th:if=${param.error} th:text="账户密码错误,请重新登录"></label>
</body>index.html
<body>
this is Main page!
<a href="/main">权限页面</a>
<a href="/logout">注销</a>
</body>main.html
<body>
本页面需要权限访问
<a href="/logout">注销</a>
</body>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<GrantedAuthority> 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<Permission> 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<Permission> list = userDao.findPermissionByUserName(username);
List<GrantedAuthority> authorities = new ArrayList<>();
/*
* 将getPermTag()构建一个GrantedAuthority接口实例对象,放于List<GrantedAuthority>中
* */
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());
}
}
版权声明:本文为u011573295原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。