基于SpringSecurity实现RBAC权限控制
基于SpringSecurity实现RBAC权限控制
mapper
package com.po.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.po.domain.Permission;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface PermissionMapper extends BaseMapper<Permission> {
/**
* 根据用户ID查询权限
*
* @param id
* @return
*/
@Select("SELECT p.* FROM t_permission p,t_role_permission rp,t_role r,t_user_role ur,t_user u " +
"WHERE p.id = rp.PID AND rp.RID = r.id AND r.id = ur.RID AND ur.UID = u.id AND u.id =#{id}")
List<Permission> findByUserId(Integer id);
}
service
package com.po.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.po.domain.Permission;
import java.util.List;
public interface PermissionService extends IService<Permission> {
// 根据用户ID查询对应的权限
List<Permission> findByUserId(Integer id);
}
package com.po.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.po.domain.Permission;
import com.po.mapper.PermissionMapper;
import com.po.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 权限Service
*/
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
@Autowired
PermissionMapper permissionMapper;
/**
* 根据用户ID查询权限列表
*
* @return
*/
@Override
public List<Permission> findByUserId(Integer id) {
return permissionMapper.findByUserId(id);
}
}
userdetailservice
package com.po.service.impl;
import com.po.domain.MyUserDetails;
import com.po.domain.Permission;
import com.po.domain.User;
import com.po.mapper.MyUserDetailsServiceMapper;
import com.po.service.PermissionService;
import com.po.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class MyUserDetailsService implements UserDetailsService {
@Resource
private PermissionService permissionService;
@Resource
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("user is ==>" + username);
}
// 先声明一个权限集合, 因为构造方法里面不能传入null
Collection<GrantedAuthority> authorities = new ArrayList<>();
List<Permission> permissionList= permissionService.findByUserId(user.getId());
for (Permission permission : permissionList) {
authorities.add(new SimpleGrantedAuthority(permission.getPermissionTag()));
}
UserDetails userDetails = new org.springframework.security.core.userdetails.User(username,
"{bcrypt}"+user.getPassword(),//不使用密码加密
true, //用户是否启用 (true:启用)
true,//用户是否过期 (true:没有过期)
true, //用户凭证是否过期 (true:没有过期)
true, // 用户是否锁定 (true:没有锁定)
authorities);
return userDetails;
}
}
给登录用户进行授权
package com.po.config;
import com.po.domain.Permission;
import com.po.filter.ValidateCodeFilter;
import com.po.handler.MyAccessDeniedHandler;
import com.po.service.PermissionService;
import com.po.service.impl.MyAuthenticationService;
import com.po.service.impl.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.List;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启注解支持
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService myUserDetailsService;
@Autowired
ValidateCodeFilter validateCodeFilter;
@Autowired
MyAccessDeniedHandler accessDeniedHandler;
@Resource
private PermissionService permissionService;
/**
* http请求方法
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
/** http.httpBasic() //开启httpBasic认证
.and().authorizeRequests().anyRequest().authenticated(); //所有请求都需要认证之后访问
*/
// 将验证码过滤器添加在UsernamePasswordAuthenticationFilter过滤器的前面
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);
// 设置/user/** 访问需要ADMIN角色
// http.authorizeRequests().antMatchers("/user/**").hasRole("ADMIN");
//使用自定义Bean授权
/* http.authorizeRequests().antMatchers("/user/**").
access("@myAuthorizationService.check(authentication,request)");*/
//使用自定义Bean授权,并携带路径参数
/* http.authorizeRequests().antMatchers("/user/delete/{id}").
access("@myAuthorizationService.check(authentication,request,#id)");*/
//查询数据库所有权限列表
List<Permission> permissionList=permissionService.list();
for (Permission permission : permissionList) {
//添加请求权限
http.authorizeRequests().antMatchers(permission.getPermissionUrl())
.hasAuthority(permission.getPermissionTag());
}
// 设置自定义权限不足信息.
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
/* http.formLogin().loginPage("/login.html")//开启表单认证
// .and().authorizeRequests() //放行登录页面
// .anyRequest().authenticated();
// .and().authorizeRequests().antMatchers("/login.html").permitAll() //放行登录页面
.and().authorizeRequests().antMatchers("/toLoginPage").permitAll() //放行登录页面
.anyRequest().authenticated();*/
http.formLogin() //开启表单认证
.loginPage("/toLoginPage") // 自定义登陆页面
.loginProcessingUrl("/login") //表单提交路径
.usernameParameter("username").passwordParameter("password") //自定义input额name值和password
.successForwardUrl("/") //登录成功之后跳转的路径
.successHandler(myAuthenticationService) // 登录成功处理
.failureHandler(myAuthenticationService) //登录失败处理
.and().logout().logoutUrl("/logout") //退出
.logoutSuccessHandler(myAuthenticationService) //退出后处理
.and().authorizeRequests().antMatchers("/toLoginPage").permitAll() //放行登录页面
.anyRequest().authenticated()
.and().rememberMe() //开启记住我功能
.tokenValiditySeconds(1209600) //token失效时间,默认失效时间是两周
.rememberMeParameter("remember-me") // 自定义表单name值
.tokenRepository(getPersistentTokenRepository()) //设置PersistentTokenRepository
.and().headers().frameOptions().sameOrigin() //加载同源域名下iframe页面
.and().csrf().disable();//关闭csrf防护
}
@Override
public void configure(WebSecurity web) throws Exception {
//解决静态资源被拦截的问题
web.ignoring().antMatchers("/css/**","/images/**","/js/**","/code/**");
}
/**
*身份安全管理器
* @param auth
* @throws Exception
*/
/*
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService);
}*/
@Autowired
DataSource dataSource;
/**
* 负责token与数据库之间的操作
* @return
*/
@Bean
public PersistentTokenRepository getPersistentTokenRepository(){
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource); //设置数据源
tokenRepository.setCreateTableOnStartup(false); //启动时帮助我们自动创建一张表,第一次启动设置为true,第二次启动程序的时候设置false或者注释掉;
return tokenRepository;
}
@Autowired
private MyAuthenticationService myAuthenticationService;
/* @Bean("passwordEncoder")
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}*/
@Resource
private MyUserDetailsService userDetailsService;
/**
* 身份安全管理器
* @param builder
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService)
;
}
}
浙公网安备 33010602011771号