我是靠谱客的博主 辛勤毛巾,最近开发中收集的这篇文章主要介绍SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的 realm7.方法上加权限8,运行效果9.源码地址:,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
1.shiro apache出品的很好用的权限框架,理论上来说只需要程序员配置两个类,shiro就能为我们工作起来。
这几天研究shiro,集成到springboot中,并使用注解权限,踩了不少坑,希望这篇文章能够帮助到大家
本文我将讲述一下springboot整合shiro,使用 @RequiresPermissions 进行控制器权限控制
1.数据库表设计
具体sql文件以及初始化数据在这里:https://github.com/winterme/pkusoft/blob/master/src/sql/user_center.sql
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`uid` varchar(36) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`password_salt` varchar(255) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`create_user` varchar(255) DEFAULT NULL,
`create_uid` varchar(36) DEFAULT NULL,
`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
`rid` varchar(36) DEFAULT NULL,
`pid` varchar(36) DEFAULT NULL,
`role_name` varchar(255) DEFAULT NULL,
`create_user` varchar(255) DEFAULT NULL,
`create_uid` varchar(36) DEFAULT NULL,
`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`id` varchar(36) NOT NULL,
`uid` varchar(36) NOT NULL,
`rid` varchar(36) NOT NULL,
`create_user` varchar(255) DEFAULT NULL,
`create_uid` varchar(36) DEFAULT NULL,
`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
`pid` varchar(36) NOT NULL,
`permission_name` varchar(255) DEFAULT NULL,
`permission` varchar(255) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`create_user` varchar(255) DEFAULT NULL,
`create_uid` varchar(36) DEFAULT NULL,
`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.实体:
在user里面放入 roles和permisssion 两个属性,用来查询user 的时候手动关联查出 该用户的角色和权限
@Table(name = "sys_user")
public class SysUser {
@Id
private String uid;
private String username;
private String password;
@Column(name = "password_salt")
private String passwordSalt;
// 所有的角色
private List<String> roles;
// 所有的权限
private List<String> permission;
private String status;
@Column(name = "create_user")
private String createUser;
@Column(name = "create_uid")
private String createUid;
@Column(name = "create_time")
private Date createTime;
.....getset
3.查询当前登陆用户方法,获取所有角色,所有权限
@Override
public SysUser getUserByUserNameWithPermission(String username) {
// 用户名唯一,此处用用户名查出当前用户
Example example = new Example(SysUser.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("username",username);
List<SysUser> lists = sysUserMapper.selectByExample(example);
if( lists.size()==0 ){
return null;
}
SysUser sysUser = lists.get(0);
// 查出所有的角色名
List<SysRolePermission> roles = sysRolePermissionMapper.getRoleNameByUserId(sysUser.getUid());
// 查出所有的权限
List<SysPermission> permissions = sysPermissionMapper.getSysPermissionByUid(sysUser.getUid());
// roleName
List<String> rolesName = new ArrayList<>();
for (SysRolePermission role : roles ) {
rolesName.add( role.getRoleName() );
}
sysUser.setRoles( rolesName );
// permissions
List<String> permissionsByUser = new ArrayList<>();
for (SysPermission p : permissions) {
permissionsByUser.add( p.getPermission() );
}
sysUser.setPermission( permissionsByUser );
return sysUser;
}
4.pom配置
<!-- shiro 相关包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- End -->
此处的 ${shiro.version} 使用 1.4.0 版本
5.shiroConfig配置
注意看代码上的注释
/**
* shiro 配置
*/
@Configuration
public class ShiroConfig {
private final static Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
// 下面两个方法对 注解权限起作用有很大的关系,请把这两个方法,放在配置的最上面
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
autoProxyCreator.setProxyTargetClass(true);
return autoProxyCreator;
}
//将自己的验证方式加入容器
@Bean
public MyRealm myRealm() {
System.out.println( "注入 realm" );
MyRealm myRealm = new MyRealm();
return myRealm;
}
//配置shiro session 的一个管理器
@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// 设置session过期时间
sessionManager.setGlobalSessionTimeout(60*60*1000);
return sessionManager;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm( myRealm() );
//defaultWebSecurityManager.setSessionManager( getDefaultWebSessionManager() );
return defaultWebSecurityManager;
}
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
System.out.println( "shiro 过滤器" );
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/login", "anon");
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login.html");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index.html");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}
6.配置自己的 realm
/**
* 自定义 realm
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private SysUserService sysUserService;
@Override
public String getName() {
return "myRealm";
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 从session中获取 user 对象
Session session = SecurityUtils.getSubject().getSession();
SysUser user = (SysUser)session.getAttribute("USER_SESSION");
System.out.println( "执行了================>" );
// 权限信息对象
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles( user.getRoles() );
info.addStringPermissions( user.getPermission() );
Set<String> roles = info.getRoles();
for (String str : roles) {
System.out.println( "角色:"+ str );
}
Set<String> permissions = info.getStringPermissions();
for (String str : permissions) {
System.out.println( "权限:"+ str );
}
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
String username = (String)authenticationToken.getPrincipal();
String password = new String((char[])authenticationToken.getCredentials());
System.out.println( "username="+username+",password="+password );
// 获取用户名。通过 username 找到该用户
SysUser user = sysUserService.getUserByUserNameWithPermission(username);
if( !"1".equals(user.getStatus()) ){
throw new LockedAccountException();
}
// 从数据库查询出来的用户名密码,进行验证
// 用户名,密码,密码盐值,realm 名称
// 登陆的时候直接调用 subject.login() 即可自动调用该方法
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
authenticationToken.getPrincipal() , user.getPassword() , getName()
);
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("USER_SESSION", user);
return info;
}
}
7.方法上加权限
@RequestMapping("/licm/getMsgById/{id}")
@ResponseBody
@RequiresPermissions(value = {"msg:find"})
public JsonResult getMsgById(@PathVariable("id")String id){
try {
Msg msg = msgService.selectMsgById(id);
return new JsonResult(true,msg);
} catch (Exception e) {
logger.error("查询失败!");
return new JsonResult(false,"");
}
}
@RequestMapping("/licm/getMsgByPage/{start}/{size}")
@ResponseBody
@RequiresPermissions(value = {"msg:list"})
public JsonResult getMsgById(@PathVariable("start")int start,@PathVariable("size")int size){
try {
Map<String , Object> result = msgService.selectListMsgByPage(start,size);
return new JsonResult(true, result);
} catch (Exception e) {
logger.error("查询失败!");
return new JsonResult(false,"");
}
}
8,运行效果
9.源码地址:
https://github.com/winterme/pkusoft/
最后
以上就是辛勤毛巾为你收集整理的SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的 realm7.方法上加权限8,运行效果9.源码地址:的全部内容,希望文章能够帮你解决SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的 realm7.方法上加权限8,运行效果9.源码地址:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复