本文属于原创,说明简介,如果有问题,可留言一起探讨
1.搭建springboot项目,这里不做概述
2.引入shiro 依赖
<!-- apache shiro 权限框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
3.创建ShiroRealm
package wx.milk.web.controller.admin;
import org.apache.shiro.SecurityUtils;
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 org.springframework.stereotype.Component;
import wx.milk.service.admin.IUserService;
import wx.milk.web.utils.SpringBeanFactoryUtils;
import wx.query.Query;
import wx.query.Statement;
import wx.security.User;
import java.util.HashSet;
import java.util.Set;
/**
* Created by zhong.h on 2018/6/13/013.
*/
@Component
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private IUserService service;
/* 认证.登录 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
if (service == null) {
service = SpringBeanFactoryUtils.getBean(IUserService.class);
}
UsernamePasswordToken userToken = (UsernamePasswordToken) token;//获取用户输入的token
String account = userToken.getUsername();
Query query = new Query();
Statement statement = new Statement();
statement.setName("account");
statement.setValue(account);
query.and(statement);
User user = service.findByParam(query);
return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码
}
/**
* 授权用户权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//获取用户
User user = (User) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取用户角色
Set<String> roleSet = new HashSet<String>();
roleSet.add("100002");
info.setRoles(roleSet);
//获取用户权限
Set<String> permissionSet = new HashSet<String>();
permissionSet.add("权限添加");
permissionSet.add("权限删除");
info.setStringPermissions(permissionSet);
return info;
}
}
4.创建configuration
package wx.milk.web.configuration;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import wx.milk.web.controller.admin.ShiroRealm;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by zhong.h on 2018/6/13/013.
*/
@Configuration
public class ShiroConfiguration {
public ShiroRealm shiroRealm(){
return new ShiroRealm();
}
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
*
* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔
* 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/admin/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/admin/index");
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
//自定义拦截器
Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
//限制同一帐号同时在线的个数。
//filtersMap.put("kickout", kickoutSessionControlFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// 权限控制map.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置不会被拦截的链接 顺序判断
// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
// 从数据库获取动态的权限
// filterChainDefinitionMap.put("/add", "perms[权限添加]");
// <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//logout这个拦截器是shiro已经实现好了的。
// 从数据库获取
/*List<SysPermissionInit> list = sysPermissionInitService.selectAll();
for (SysPermissionInit sysPermissionInit : list) {
filterChainDefinitionMap.put(sysPermissionInit.getUrl(),
sysPermissionInit.getPermissionInit());
}*/
shiroFilterFactoryBean
.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(shiroRealm());
// 自定义缓存实现 使用redis
//securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
//securityManager.setSessionManager(sessionManager());
//注入记住我管理器;
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
/**
* cookie对象;
* @return
*/
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//<!-- 记住我cookie生效时间30天 ,单位秒;-->
simpleCookie.setMaxAge(2592000);
return simpleCookie;
}
/**
* cookie管理对象;记住我功能
* @return
*/
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
}
5. 测试
@RequestMapping(value = "/signin")
public String login(HttpServletRequest request, HttpSession session,
String account, String password, String validatecode)
throws JsonManagerException {
String exception = (String) request.getAttribute("shiroLoginFailure");
if (StringUtils.isEmpty(account) || StringUtils.isEmpty(password)) {
return null;
}
try {
UsernamePasswordToken token = new UsernamePasswordToken(account, password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
User user=(User) subject.getPrincipal();
session.setAttribute("user", user);
return "/admin/index";
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw e;
}
6。重要工具类
package wx.milk.web.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* spring加载时候,注入的bean 的顺序是 先是Lisener 然后是 Filter 最后是 Servlet
* 因此如果在过滤器或者监听器里面注入service等会是空,因为在过滤器或者监听器加载的时候
* Servlet,service等还没有加载,因此是空的,所以就手动注入
*
* Created by zhong.h on 2018/6/13/013.
*/
@Component
public class SpringBeanFactoryUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (SpringBeanFactoryUtils.applicationContext == null) {
SpringBeanFactoryUtils.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//根据名称(@Resource 注解)
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//根据类型(@Autowired)
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
本文介绍如何在Spring Boot项目中集成Apache Shiro进行权限管理,包括Shiro依赖引入、自定义ShiroRealm实现认证与授权、配置ShiroFilter进行拦截及登录逻辑。
1万+

被折叠的 条评论
为什么被折叠?



