最近在学习shiro框架的使用,在网上找了个免费的shiro视频学习,然后整合进springboot项目中,这里只是实现了登录验证与简单的权限验证功能demo,暂时没有添加cache缓存功能。这里做一个记录。
shiro视频学习网站:https://www.imooc.com/video/16949
shiro内置两个realm ,iniRealm和jdbcRealm,但是一般我们都自定义realm
@Service
public class ShiroRealm extends AuthorizingRealm {
@Resource
private UserMapper userMapper;
/**
* * 获取登录用户的权限信息并进行封装.
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户信息
User user= (User) principalCollection.getPrimaryPrincipal();
//查询数据库获取用户角色并进行校验
List<String> roleName=userMapper.selectRolesByUserId(user.getId());
if (roleName==null || roleName.size()==0)
throw new AuthorizationException();
Set<String> roles= new HashSet<>();
for (String role: roleName) {
roles.add(role);
}
//查询数据库获取用户权限
List<String> pers=userMapper.selectPermissionByUserId(user.getId());
if (pers==null||pers.size()==0)
throw new AuthorizationException();
Set<String> permissions=new HashSet<>();
for (String per : pers) {
permissions.add(per);
}
//构建授权对象
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setRoles(roles);//设置用户角色
simpleAuthorizationInfo.setStringPermissions(permissions);//设置用户权限
return simpleAuthorizationInfo;
}
/**
* 通过此方法获取用户认证信息,并进行封装,然后返回给
* SecurityManager对象
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//通过登录时提交的token获取用户名
String username= (String) authenticationToken.getPrincipal();
//在数据库中根据查询用户是否存在
User user=userMapper.selectUserByUserName(username);
//如果用户不存在,抛出异常
if (user==null){
throw new UnknownAccountException();
}
//如果用户存在,封装认证信息
SimpleAuthenticationInfo
simpleAuthenticationInfo=new SimpleAuthenticationInfo(user,
user.getPassword(), ByteSource.Util.bytes("mark"),getName());
return simpleAuthenticationInfo;
}
}
再配置shiro初始化配置与过滤器,因为我做的是springboot项目,所以是创建ShiroConfig配置类就行。
@Configuration
public class ShiroConfig {
/**
* 配置SecurityManager对象(shiro核心安全管理器对象)
* @param shiroRealm
* @return
*/
@Bean
public SecurityManager securityManager(ShiroRealm shiroRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//构建凭证匹配对象
HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");//设置加密方式
matcher.setHashIterations(1);//设置加密次数
shiroRealm.setCredentialsMatcher(matcher);
defaultWebSecurityManager.setRealm(shiroRealm);
return defaultWebSecurityManager;
}
/**
* * 配置ShiroFilterFactoryBean对象,通过此对象
* * 创建过滤器工厂,并指定过滤规则
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map=new LinkedHashMap<>();
map.put("/index/login","anon");
map.put("/user/index","anon");
map.put("/user/login","anon");
map.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//===========授权配置============
/**
* spring 框架管理此对象时,会基于此对象管理
* Shiro框架中相关API对象的生命周期
*/
@Bean //<bean id="" class="">
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 配置Advisor对象,此对象中会对切入点,通知等对象进行
* 相关描述,后续DefaultAdvisorAutoProxyCreator对象
* 会基于描述,为目标对象创建代理对象
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor
authorizationAttributeSourceAdvisor(
SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor=
new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
查询数据库的操作,实体类自己创建,数据库在最后
@Mapper
public interface UserMapper {
@Select("select * from user where username=#{username}")
User selectUserByUserName(String username);
@Select("select role_name from roles where id in(select role_id from user_role where user_id=#{id})")
List<String> selectRolesByUserId(int id);
@Select("select permission_name from permission where id in (select permission_id from role_permission where role_id in (select role_id from user_role where user_id=#{id}))")
List<String> selectPermissionByUserId(int id);
}
抛出异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public JsonResult doHandleRuntimeException(RuntimeException e){
e.printStackTrace();
return new JsonResult(e.getMessage());
}
@ExceptionHandler(ShiroException.class)
@ResponseBody
public JsonResult doHandleShiroException(ShiroException e){
JsonResult result = new JsonResult();
result.setState(0);
if(e instanceof UnknownAccountException) {
result.setMessage("账户不存在");
}else if(e instanceof LockedAccountException) {
result.setMessage("账户已被禁用");
}else if(e instanceof IncorrectCredentialsException) {
result.setMessage("密码不正确");
}else if(e instanceof AuthorizationException) {
result.setMessage("没有此操作权限");
}else {
result.setMessage("系统维护中");
}
e.printStackTrace();
return result;
}
}
JsonResult 是我对返回前端json格式数据的封装
@Data
public class JsonResult implements Serializable {
/*状态码*/
private int state = 1;//1.表示SUCCESS,0.表示ERROR
/*状态信息*/
private String message = "ok";
/*正确数据*/
private Object data;
public JsonResult(String message) {
this.message = message;
}
public JsonResult(Object data) {
this.data = data;
}
public JsonResult(int state, String message) {
this.state = state;
this.message = message;
}
public JsonResult(Throwable e) {
this.state = 0;
this.message = e.getMessage();
}
public JsonResult() {
super();
}
}
实现controller控制类,创建测试接口
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/index")
public String index(){
return "login";
}
@RequestMapping("/login")
@ResponseBody
public JsonResult login(User user){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
subject.login(token);
return new JsonResult(token);
}
//根据角色做权限验证
@RequiresRoles(value = {"admin","vip"},logical = Logical.OR)
@RequestMapping("/testRoles")
@ResponseBody
public String testRoles(){
return "success admin";
}
//根据权限进行shiro验证
@RequiresPermissions("sys:select")
@RequestMapping("/testPermission")
@ResponseBody
public String testPermission(){
return "success testPermission";
}
}
测试接口:
http://localhost:8083/user/index
登录后进行角色权限测试:http://localhost:8083/user/testRoles
把这个demo上传到github中了,可以直接下载运行
github: https://github.com/sunyucheng123/shiro_demo.git
sql数据库不知道为什么不能导入进来,如果想看可以直接去GitHub中查看。
版权声明:本文为S_Y_C_1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。