您的位置:首页 > Web前端 > Vue.js

Shiro+Springboot+Vue前后端分离实现权限管理

2020-01-13 09:51 1036 查看

Shiro介绍就跳过了,这里记录怎么在项目中使用

1 添加maven依赖

[code]<shiro.version>1.4.0</shiro.version>
<druid.version>1.1.20</druid.version>
<shiro-redis.version>3.2.3</shiro-redis.version>

   

[code]<dependency>
<!--session持久化插件-->
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>${shiro-redis.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- shiro-core -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
[/code]

2 建好 用户表(我这里是whaccount),角色表(role),用户角色中间表,权限表(或者叫菜单表,menu),角色-权限(菜单)中间表这5张表

   具体的RBAC概念这里我就不细说了 网上一大堆解释,用户对应角色,角色对应权限

3 实现自定义Realm

   

package com.hy.bjggwhy.config;

import com.hy.bjggwhy.entity.WhyMenu;
import com.hy.bjggwhy.entity.WhyRole;
import com.hy.bjggwhy.entity.WhyWhaccount;
import com.hy.bjggwhy.service.WhyMenuService;
import com.hy.bjggwhy.service.WhyRoleService;
import com.hy.bjggwhy.service.WhyWhaccountService;
import com.hy.bjggwhy.util.Utils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
* @author zhangmy
* @date 2019-12-24 15:57
* @description 配置Realm类(shiro框架手动配置的关键,用来登陆和权限认证)
*/
public class WhyShiroRealm extends AuthorizingRealm {

private static final Logger LOGGER = LoggerFactory.getLogger(WhyShiroRealm.class);

@Autowired
private WhyWhaccountService whaccountService;

@Autowired
private WhyRoleService roleService;

@Autowired
private WhyMenuService menuService;

//授权配置
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
LOGGER.info("权限配置-->WhyShiroRealm.doGetAuthorizationInfo:");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
WhyWhaccount whaccount = (WhyWhaccount)principals.getPrimaryPrincipal();
try {
List<WhyRole> roles = roleService.getRoleByWhaccountId(whaccount.getId());
for (WhyRole role : roles) {
authorizationInfo.addRole(role.getName());//角色存储
}
//此处如果多个角色都拥有某项权限,不会数据重复,内部用的是Set
List<WhyMenu> menus = menuService.getMenuByRoleList(roles);
for (WhyMenu menu : menus) {
authorizationInfo.addStringPermission(menu.getUrl());//权限存储
}
} catch (Exception e) {
Utils.getExceptionDetail(e);
}
return authorizationInfo;
}

//认证配置
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
LOGGER.info("Shiro认证-->WhyShiroRealm.doGetAuthenticationInfo:");
//获取用户的输入的账号.
String username = (String) token.getPrincipal();
WhyWhaccount whaccount = whaccountService.findWhaccountByUsername(username);
if (whaccount == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
whaccount, //用户名
whaccount.getPassword(), //密码
null,//salt
getName()  //realm name
);
return authenticationInfo;
}
}

  4 添加Shiro配置,通过ShiroConfig类实现

    

package com.hy.bjggwhy.config;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author zhangmy
* @date 2019-12-24 16:46
* @description
*/
@Configuration
//@ComponentScan
public class ShiroConfig {

@Bean
public FilterRegistrationBean delegatingFilterProxy() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
proxy.setTargetFilterLifecycle(true);
proxy.setTargetBeanName("shiroFilter");
filterRegistrationBean.setFilter(proxy);
return filterRegistrationBean;
}

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
// shiroFilterFactoryBean.setLoginUrl("/login");
//设置成功跳转的页面
//shiroFilterFactoryBean.setSuccessUrl("/index");
// 设置无权限时跳转的 url;
//shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");

// 设置拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

//开放接口
//        filterChainDefinitionMap.put("/**", "anon");//放开全部

filterChainDefinitionMap.put("/whaccount/whaccountLogin", "anon");  //放开登录
filterChainDefinitionMap.put("/*/get*", "anon"); //放开查询
filterChainDefinitionMap.put("/upload/*", "anon"); //放开资源上传
filterChainDefinitionMap.put("/search/*", "anon"); //放开资源搜索
filterChainDefinitionMap.put("/user/*", "anon"); //放开普通用户操作

filterChainDefinitionMap.put("/swagger-ui.html", "anon"); //放开swagger
filterChainDefinitionMap.put("/swagger-resources/**", "anon"); //放开swagger
filterChainDefinitionMap.put("/v2/**", "anon"); //放开swagger
filterChainDefinitionMap.put("/webjars/**", "anon"); //放开swagger

filterChainDefinitionMap.put("/**", "authc");//其余接口一律拦截,这行代码必须放在所有权限设置的最后,不然都被拦截

//配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
//shiroFilterFactoryBean.setLoginUrl("/unauth");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
System.out.println("Shiro拦截器工厂类注入成功");
return shiroFilterFactoryBean;
}

/*
自定义身份认证realm
必须写上这个类,并加上@Bean注解,目的是注入CustomRealm
否则会影响CustomRealm类中其他类的依赖注入
*/
@Bean
public WhyShiroRealm customRealm(){
WhyShiroRealm shiroRealm = new WhyShiroRealm();
//shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());// 将md5密码比对器传给realm
return  shiroRealm;
}

/*
注入securityManager
*/
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置REALM
securityManager.setRealm(customRealm());
return securityManager;
}

/*
开启注解支持
*/
@Bean
//@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
}

5 登录接口做shiro认证

   

private Response login(String username, String password){
//shiro登录验证
Subject subject = SecurityUtils.getSubject();
String realPassword = MD5Utils.GetMD5Code(password);
UsernamePasswordToken token = new UsernamePasswordToken(username, realPassword);
subject.login(token);
//用户基本信息
WhyWhaccount whyWhaccount = this.getWhaccountByUsername(username);
Jedis jedis = RedisUtil.getJedis();
String key = MD5Utils.GetMD5Code(Constant.REDIS_WHACCOUNT_USER_KEY_PREFIX + whyWhaccount.getId());
String sessionValue = MD5Utils.GetMD5Code(whyWhaccount.getId() + whyWhaccount.getUserName() + whyWhaccount.getPassword());
jedis.set(key, sessionValue);
jedis.expire(key, Constant.REDIS_SESSION_MAX_INACTIVE_INTERNAL);
Map<String, Object> loginMap = new HashMap<>();
whyWhaccount.setPassword(null);
loginMap.put("whaccount",whyWhaccount);
loginMap.put("session",sessionValue);
//拥有的角色
List<WhyRole> roles = roleService.getRoleByWhaccountId(whyWhaccount.getId());
loginMap.put("roles", roles);
//拥有的菜单权限
List<WhyMenu> menus = menuService.getMenuByRoleList(roles);
loginMap.put("menus", menus);
return new Response(Constant.RES_SUCCESS, "登录成功", loginMap);
}

6 Shiro授权

   授权方式比较多,我这里使用注解方式,即在需要授权验证的controller上面使用

@RequiresPermissions({"权限的url"})

    shiro会根据需要的权限url再去subject的权限中去对比,有就通过,没有就不通过

       

  • 点赞
  • 收藏
  • 分享
  • 文章举报
Zhangmaoyang 发布了10 篇原创文章 · 获赞 0 · 访问量 312 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐