您的位置:首页 > 编程语言 > Java开发

SpringBoot整合Shiro权限管理

2020-01-15 10:58 766 查看

SpringBoot整合Shiro权限管理

Shiro(Java安全框架)

什么是权限管理

权限管理包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
1.什么是Shiro

Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

1.三个核心组件:Subject, SecurityManager 和 Realms.

Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

2.Shiro四大核心功能:Authentication,Authorization,Cryptography,Session Management

3.用户名密码认证流程

4.授权流程

先创建一个SpringBoot项目,添加shiro的相关依赖
<!--添加 shiro 依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
修改配置文件application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/project?serverTimezone=UTC
username: root
password: 123456
thymeleaf:
cache: false
encoding: utf-8
prefix: classpath:/templates/
mybatis:
mapper-locations: classpath:/mapper/*.xml
type-aliases-package: com.shiro.login.domain
实体类

用户

@Data
public class User {

private String id;
private String name;
private String password;

}

角色

@Data
public class Role {

private String id;
private String name;

}

权限

@Data
public class Permission {

private String id;
private String name;
private String url;
}
Mapper.xml和Service层就不贴了 ShiroConfiguration
package com.shiro.login.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
* @Author: Adorez
* @Date: 2019/11/27 18:00
* @Description:
*/
@Configuration
public class ShiroConfiguration {

@Bean("userRealm")
public UserRealm userRealm(){
UserRealm userRealm=new UserRealm();
return userRealm;
}

/**
* 定义安全管理器 securityManager
* @return
*/
@Bean("securityManager")
public SecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
manager.setRealm(userRealm);
return manager;
}

@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager){
ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
//设置securityManager
bean.setSecurityManager(securityManager);
//设置登录页面
bean.setLoginUrl("/login");
//设置登录成功跳转的页面
bean.setSuccessUrl("/success");
bean.setUnauthorizedUrl("/error/unAuth");
//定义过滤器
LinkedHashMap<String,String> filter=new LinkedHashMap<>();
filter.put("/","authc");//首页需要认证
filter.put("/login","anon");//登录页面无需认证
filter.put("/toLogin","anon");//登录页面无需认证
filter.put("/vip/index","roles[vip]");//添加权限配置
filter.put("/error/unAuth","authc");
//需要登录访问的资源,一般将/**放在最下边
filter.put("/**","authc");
bean.setFilterChainDefinitionMap(filter);
return bean;
}

/**
* 配置shiro和spring的关联
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}

/**
* lifecycleBeanPostProcessor 是负责生命周期的 初始化和销毁的类
* @return
*/
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* Spring 的一个 bean , 由 Advisor 决定对哪些类的方法进行 AOP 代理 .
* @return
*/
@Bean
public static DefaultAdvisorAutoProxyCreator
getDefaultAdvisorAutoProxyCreator(){
return new DefaultAdvisorAutoProxyCreator();
}
/**
* 页面上使用shiro标签
* @return
*/
@Bean(name = "shiroDialect")
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
UserRealm
package com.shiro.login.config;

import com.shiro.login.domain.Permission;
import com.shiro.login.domain.Role;
import com.shiro.login.domain.User;
import com.shiro.login.service.PermissionService;
import com.shiro.login.service.RoleService;
import com.shiro.login.service.UserService;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
* @Author: Adorez
* @Date: 2019/11/27 18:13
* @Description:
*/
public class UserRealm extends AuthorizingRealm {

@Autowired
private UserService userService;

@Autowired
private RoleService roleService;

@Autowired
private PermissionService permissionService;

/**
* 为用户授权
* 角色权限和对应的权限添加
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("为用户授权");
//获取登录用户名
User userInfo = (User) principalCollection.getPrimaryPrincipal();
//查询用户名称
User user = userService.findUserByuserName(userInfo.getName());
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
//根据查询出来的用户信息获得角色
Role role = roleService.findById(Integer.valueOf(user.getId()));
//添加角色1
simpleAuthorizationInfo.addRole(role.getName());
//根据查询出来的角色查询权限
List<Permission> perList = permissionService.findById(Integer.valueOf(role.getId()));

for (Permission per:perList) {
//添加权限
simpleAuthorizationInfo.addStringPermission(per.getName());
}
return simpleAuthorizationInfo;
}

/**
* 认证登录
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("---认证登录");
//token携带了用户信息
UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)token;
//获取前端输入的用户名
String username = usernamePasswordToken.getUsername();
//根据用户名查询数据库中对应的记录
User user = userService.findUserByuserName(username);
if (null==user) {
new UnknownAccountException("账户不存在");
}else {
new IncorrectCredentialsException("密码不正确");
}
//当前realm对象的name
String realmName = getName();
//盐值
ByteSource source=ByteSource.Util.bytes(user.getName());
/**
* 封装用户信息,构建authenticationInfo对象并返回
* 参数一:用户对象
* 参数二:密码
* 参数三:盐值
* 参数四:realm的名字
*/
AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(),source,realmName);
return authenticationInfo;
}
}
Controller
package com.shiro.login.controller;

import com.shiro.login.domain.User;
import com.shiro.login.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpSession;

/**
* @Author: Adorez
* @Date: 2019/11/27 17:57
* @Description:
*/
@Controller
public class UserController {

@Autowired
private UserService userService;

@PostMapping("/toLogin")
public String login(User user, HttpSession session){
//通过SecurityUtils.getSubject()可以获得当前的Subject
Subject subject = SecurityUtils.getSubject();
//判断是否有登录信息
if(!subject.isAuthenticated()){
UsernamePasswordToken token=new UsernamePasswordToken(user.getName(),user.getPassword());
try {
//执行认证操作
subject.login(token);
session.setAttribute("user", subject.getPrincipal());//getPrincipal()得到当前登录的用户名
}catch (Exception e){
System.out.println(e.getStackTrace());
return "redirect:login";
}
}
return "redirect:/";
}
@GetMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
if (subject!=null) {
subject.logout();
}
return "login";
}
}

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>用户登录</h1>
<hr>
<form id="from" th:action="@{/toLogin}" method="post">
<table>
<tr>
<td>用户名</td>
<td>
<input type="text" name="name" placeholder="请输入账户名"/>
</td>
</tr>
<tr>
<td>密码</td>
<td>
<input type="password" name="password" placeholder="请输入密码"/>
</td>
</tr>
<tr>
<td colspan="2">
<font color="red">[[${msg}]]</font>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</form>
</body>
</html>

index.html

<!DOCTYPE html>
<html xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<hr>
<ul>
<li><a href="/user/index">个人中心</a></li>
<shiro:hasRole name="vip"><li><a href="/vip/index">会员中心</a></li></shiro:hasRole>
<li><a href="/test/index">hei</a></li>
<li><a href="logout">退出登录</a></li>
</ul>
</body>
</html>

error/unAuth.html

<!DOCTYPE html>
<html>
<head>
<title>未授权提示</title>
</head>
<body>
<h1>您还不是<font color="red">会员</font>,没有权限访问这个页面!</h1>
</body>
</html>

shiro标签的使用

guest标签 验证当前用户是否为“访客”,即未认证(包含未记住)的用户
user标签 认证通过或已记住的用户
authenticated标签 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在
notAuthenticated 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户
principal 输出当前用户信息,通常为登录帐号信息
hasRole 验证当前用户是否属于该角色
lacksRole 与hasRole标签逻辑相反,当用户不属于该角色时验证通过
hasAnyRole 验证当前用户是否属于以下任意一个角色
hasPermission 验证当前用户是否拥有指定权限
lacksPermission 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过

项目具体实现
链接:https://pan.baidu.com/s/1RKzOZFU81XgJJ2di7nFpCA
提取码:qzp4

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