一、demo:
1、pom:
<groupId>com.demo.shiro</groupId>
<artifactId>shiro-filter-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!-- AOP依赖,必须,否则shiro权限拦截验证不生效 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
2、Realm:这里没有连接数据库,在UserConstants中假设数据
/**
* 模拟数据库查询数据,假设有:用户名/密码/角色/资源
* admin/123/xtgly/user_manage、role_manage、menu_manage、school_manage
* zs/123/userAdmin、roleAdmin/user_manage、role_manage、menu_manage
* ls/123/schoolAdmin/school_manage
*/
public class UserConstants {
public static Map<String, String> getUsers() {
Map<String,String> users = new HashMap<>();
users.put("admin","123");
users.put("zs","123");
users.put("ls","123");
return users;
}
public static Map<String,List<String>> getUserRoles() {
Map<String,List<String>> userRoles = new HashMap<>();
//admin
List<String> adminRoles = new ArrayList<>();
adminRoles.add("xtgly");
userRoles.put("admin",adminRoles);
//zs
List<String> zsRoles = new ArrayList<>();
zsRoles.add("userAdmin");
zsRoles.add("roleAdmin");
userRoles.put("zs",zsRoles);
//ls
List<String> lsRoles = new ArrayList<>();
lsRoles.add("schoolAdmin");
userRoles.put("ls",lsRoles);
return userRoles;
}
public static Map<String,List<String>> getUserPermissions() {
Map<String,List<String>> userPermissions = new HashMap<>();
List<String> lsPermissions = new ArrayList<>();
//ls
lsPermissions.add("school_manage");
userPermissions.put("ls",lsPermissions);
//zs
List<String> zsPermissions = new ArrayList<>();
zsPermissions.add("user_manage");
zsPermissions.add("role_manage");
zsPermissions.add("menu_manage");
userPermissions.put("zs",zsPermissions);
//admin
List<String> adminPermissions = new ArrayList<>();
adminPermissions.add("school_manage");
userPermissions.put("admin",adminPermissions);
return userPermissions;
}
}
public class MyRolePermissionRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
String primaryPrincipal = (String) principal.getPrimaryPrincipal();
Map<String, List<String>> userRoles = UserConstants.getUserRoles();
List<String> roles = userRoles.get(primaryPrincipal);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRoles(roles);
//资源
Map<String, List<String>> userPermissions = UserConstants.getUserPermissions();
List<String> permissions = userPermissions.get(primaryPrincipal);
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
Map<String,String> dbUsers = UserConstants.getUsers();
Set<String> dbUserNames = dbUsers.keySet();
//验证用户名
if(!dbUserNames.contains(username)){
throw new UnknownAccountException();
}
//验证密码
String dbPwd = dbUsers.get(username);
if(!dbPwd.equals(password)){
throw new IncorrectCredentialsException();
}
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,this.getName());
return simpleAuthenticationInfo;
}
}
3、拦截器:
public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter{
Logger logger = LoggerFactory.getLogger(ShiroFormAuthenticationFilter.class);
/**
* 未登陆
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (!isLoginRequest(request, response)) {
this.handleErrorMsg(request,response);
return false;
}
if (isLoginSubmission(request, response)) {
if (logger.isTraceEnabled()) {
logger.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (logger.isTraceEnabled()) {
logger.trace("Login page view.");
}
return true;
}
}
private void handleErrorMsg(ServletRequest request, ServletResponse response) throws IOException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse) response;
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setContentType("application/text; charset=utf-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.println("登陆失效");
out.flush();
out.close();
}
}
4、配置文件:
import com.demo.shiro.filter.ShiroFormAuthenticationFilter;
import com.demo.shiro.realm.MyRolePermissionRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.realm.Realm;
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.apache.shiro.mgt.SecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
//域
@Bean
public Realm getMyShiroRealm(){
return new MyRolePermissionRealm();
}
//入口
@Bean
public SecurityManager getMySecurityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(this.getMyShiroRealm());
SecurityUtils.setSecurityManager(securityManager);
return securityManager;
}
//拦截器配置
@Bean
public ShiroFilterFactoryBean shirFilter() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(this.getMySecurityManager());
//shiroFilterFactoryBean.setLoginUrl("/login");
/**
* 只写这个,访问报错
* {
* "timestamp": 1703231180623,
* "status": 404,
* "error": "Not Found",
* "message": "No message available",
* "path": "/shiroTest/login.jsp"
* }
*/
Map<String, String> filterChainDefinitionMap = new HashMap<>();
filterChainDefinitionMap.put("/**","authc");
filterChainDefinitionMap.put("/login/login","anon");
LinkedHashMap<String, Filter> filtsMap=new LinkedHashMap<String, Filter>();
filtsMap.put("authc",new ShiroFormAuthenticationFilter() );
shiroFilterFactoryBean.setFilters(filtsMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//以下为注解支持配置
/**
* Shiro生命周期处理器
*/
@Bean(name = "lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
/**
* 开启Shiro-aop注解支持
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
5、util
public class SessionUtil {
public static String getUser() {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
return (String) session.getAttribute("currUserAccount");
}
}
6、controller:
@RequestMapping("/login")
@RestController
public class LoginController {
@RequestMapping("/login")
public String login(String username,String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(
username, password
);
try {
subject.login(token);
System.out.println("认证成功");
Session session = subject.getSession();
//缓存用户
session.setAttribute("currUserAccount",username);
//权限
boolean isp = subject.isPermitted("school_manage");
return (String) session.getId();
} catch (AuthenticationException e) {
System.out.println("认证失败");
e.printStackTrace();
}
return null;
}
@RequestMapping("/logOut")
public void logOut(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
}
}
@RequestMapping("/user")
@RestController
@RequiresRoles("roleAdmin")
public class UserManageController {
@RequestMapping("/test")
public String test(){
return "这是用户管理";
}
@RequestMapping("/getUser")
public String getUser(){
return SessionUtil.getUser();
}
}
@RequestMapping("/school")
@RestController
public class SchoolManageController {
@RequestMapping("/test")
@RequiresPermissions("school_manage")
public String test(){
return "这是学校管理";
}
}
测试: