项目结构
spring和shiro的整合依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency
yml文件配置
server:
port: 8081
spring:
application:
name: ihrm-company #指定服务名
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shiro_db?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
database: MySQL
show-sql: true
open-in-view: true
redis:
host: 127.0.0.1
port: 6379
userController的代码编写
import cn.itcast.shiro.domain.User;
import cn.itcast.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
import java.util.Enumeration;
@RestController
public class UserController {
@Autowired
private UserService userService;
//添加
//使用shiro注解鉴权
//@RequiresPermissions() //访问次方法必须具备的权限
// @RequiresRoles() //访问此方法必须具备的角色
/**
* 鉴权的方式
* 1.过滤器: 如果权限信息不匹配跳转到 filterFactory.setUnauthorizedUrl(""); 配置的URL
* 2. 注解: 抛出异常
*/
@RequiresPermissions("user-home")
@RequestMapping(value = "/user/home")
public String home() {
return "访问主页成功";
}
//添加
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String add() {
return "添加用户成功";
}
//查询
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String find() {
return "查询用户成功";
}
//更新
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public String update(String id) {
return "更新用户成功";
}
//删除
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public String delete() {
return "删除用户成功";
}
/**
* 1.传统登录
* 前端发送登录请求 -》接口部分获取用户名密码 -》程序员在接口部分手动控制
* <p>
* 2.shiro登录
* 前端发送登录请求-》接口部分获取用户名密码-》通过subject.login -》 realm域的认证方法
*
* @param username
* @param password
* @return
*/
//用户登录
@RequestMapping(value = "/login")
public String login(String username, String password) {
//构造登录令牌
try {
/**
* 密码加密:
* shiro提供的md5加密
* 参数一:加密的内容
* 参数二:盐(加密的混淆字符串) (可以用用户名,如果用户名不能改变)
* 参数三:加密次数
*/
password = new Md5Hash(password, username, 3).toString();
UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);
//1.获取subject
Subject subject = SecurityUtils.getSubject();
//2.调用subject进行登录
subject.login(upToken);
return "登录成功";
} catch (Exception e) {
return "用户名或密码错误";
}
}
@RequestMapping(value = "/autherror")
public String autherror(int code) {
return code == 1 ? "未登录" : "未授权";
}
}
自定义realm
package cn.itcast.shiro.realm;
import cn.itcast.shiro.domain.Permission;
import cn.itcast.shiro.domain.Role;
import cn.itcast.shiro.domain.User;
import cn.itcast.shiro.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.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义realm
*/
public class CustomRealm extends AuthorizingRealm {
public void setName(String name) {
super.setName("custRealm");
}
@Autowired
private UserService userService;
/**
* 授权方法
* 操作时候,判断用户是否具有相应的权限
* 先认证---安全数据
* 再授权---根据安全数据获取用户具有的所有操作权限
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//1.获取已认证的用户数据
User user = (User) principalCollection.getPrimaryPrincipal(); //得到唯一的安全数据
//2.根据用户数据获取用户的权限信息(所有色色,所有权限)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> roles = new HashSet<>(); //所有色色
Set<String> perms = new HashSet<>(); //所有权限
for (Role role : user.getRoles()) { //得到每一个角色
roles.add(role.getName()); //得到角色名
for (Permission perm : role.getPermissions()) {
perms.add(perm.getCode()); //得到所有权限编码
}
}
info.setStringPermissions(perms);
info.setRoles(roles);
return info;
}
/**
* 认证方法
*
* @param authenticationToken 传递的用户名和密码
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.获取登录的用户名和密码(token)
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
String username = upToken.getUsername();
String password = String.valueOf(upToken.getPassword());
//2.根据用户名查询数据库
User user = userService.findByName(username);
//3.判断用户是否存在或密码一致
if (user != null && user.getPassword().equals(password)) {
//4.如果一致返回安全数据
//构造方法:参数: 安全数据,密码,realm域名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
return info;
}
//5.不一致,返回null 抛出异常
return null;
}
}
shiro统一配置
package cn.itcast.shiro;
import cn.itcast.shiro.realm.CustomRealm;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfiguration {
//1.创建realm
@Bean
public CustomRealm getRealm() {
return new CustomRealm();
}
//2.创建安全管理器
@Bean
public SecurityManager getSecurityManager(CustomRealm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
/**
* 在web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制
*
* @param securityManager
* @return
*/
//3.配置shiro的过滤器工厂
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
//1.创建过滤器工厂
ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
//2.设置安全管理器
filterFactory.setSecurityManager(securityManager);
//3.通用配置(跳转登录页面,未授权跳转的页面)
filterFactory.setLoginUrl("/autherror?code=1"); //跳转url地址
filterFactory.setUnauthorizedUrl("/autherror?code=2"); //未授权的url
//4.设置过滤器集合
/**
* 设置所有的过滤器:有顺序 map
* key=拦截的URL地址
* value=过滤器类型
*/
Map<String, String> filterMap = new LinkedHashMap<>();
// filterMap.put("/user/home","anon"); //当前请求地址可以匿名访问
// 具有某种权限才能访问 使用过滤器的形式配置请求地址的依赖权限
// filterMap.put("/user/home","perms[user-home]"); //如果不具备指定权限,跳转到setUnauthorizedUrl指定的路径
filterMap.put("/user/home", "roles[系统管理员]"); //具备某个角色才能访问
filterMap.put("/user/**", "authc"); //当前请求地址认证后访问
filterFactory.setFilterChainDefinitionMap(filterMap);
return filterFactory;
}
//4.配置shiro注解支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
自定义公共异常处理器
package cn.itcast.shiro;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义的公共异常处理器
* 1.声明异常处理器
* 2.对异常统一处理
*/
@ControllerAdvice
public class BaseExceptionHandler {
@ExceptionHandler(value = AuthorizationException.class)
@ResponseBody
public String error(HttpServletRequest request, HttpServletResponse response,AuthorizationException e) {
return "未授权";
}
}
数据库
测试
来源:CSDN
作者:半夏少年
链接:https://blog.csdn.net/qq_41840847/article/details/104477760