博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot入门九,添加shiro支持
阅读量:7119 次
发布时间:2019-06-28

本文共 10659 字,大约阅读时间需要 35 分钟。

项目基本配置参考,使用myEclipse新建一个SpringBoot项目即可。现在来给项目添加shiro支持,数据暂时硬编码,不连接数据库,具体内容如下:

1. pom.xml添加以下配置信息

org.apache.shiro
shiro-spring-boot-starter
1.4.0

2. 创建shiro配置文件

2.1 自定义权限过滤器
package com.qfx.demo.shiro;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;import com.qfx.demo.vo.SysUser;/** * @功能描述:   拦截控制,用于替换shiro默认的roles拦截规则,改"并且(and)"为"或者 (or)" */public class CustomRolesAuthorizationFilter extends RolesAuthorizationFilter {    private final Logger logger = LogManager.getLogger(getClass());     /**         * Overriding         * @功能描述:设置同一个URL配置多个角色为"或者"的关系,默认为"并且",         *                  如:/user/** = Role["admin,user"],默认必须满足"admin","user"条件,         *                 改为"或者"之后只需要满足一个条件即可(Ini.Section中有此url,会走此方法)         * @param request         * @param response         * @param obj         * @return         * @throws Exception         */    @Override    public boolean isAccessAllowed(ServletRequest request,ServletResponse response, Object obj) {        Subject subject = getSubject(request, response);        // 验证是否登录        if (null == subject.getPrincipals()) {            return false;        }        // 获取请求地址        HttpServletRequest hsq = (HttpServletRequest) request;        String requestUrl = hsq.getServletPath();        // 获取用户信息,这里返回的对象类型与登录验证时        // new SimpleAuthenticationInfo(user, pwd, this.getName())中的第一个参数的类型需要保持一致        SysUser user = (SysUser)subject.getPrincipals().getPrimaryPrincipal();        System.out.println("--------1.开启用户["+user.getUserName()+"]访问["+requestUrl+"]的角色过滤--------");        // 获取角色信息        String[] rolesArray = (String[]) obj;        if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问            System.out.println("--------3.用户["+user.getUserName()+"]访问["+requestUrl+"]的角色过滤结束--------");            logger.info("用户["+user.getUserName()+"]访问["+requestUrl+"]无角色限制,权限验证通过!");                return true;        }            for (int i = 0; i < rolesArray.length; i++) {                    if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问                      System.out.println("--------3.用户["+user.getUserName()+"]访问["+requestUrl+"]的角色过滤结束--------");                    logger.info("用户["+user.getUserName()+"]访问["+requestUrl+"]权限验证通过!");                        return true;                    }            }        System.out.println("--------3.用户["+user.getUserName()+"]访问["+requestUrl+"]的角色过滤结束--------");        logger.info("用户["+user.getUserName()+"]访问["+requestUrl+"]权限验证失败,禁止访问!");        return false;    }}
2.2 自定义realm
package com.qfx.demo.shiro;import java.util.HashSet;import java.util.Set;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UnknownAccountException;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 com.qfx.demo.cache.UserCache;import com.qfx.demo.vo.SysUser;public class UserRealm extends AuthorizingRealm {    /**         * Overriding         * @功能描述:   权限验证         * @param arg0         * @return         */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        // 1.获取用户信息        //   这里principals.getPrimaryPrincipal()的返回的对象类型与登录验证时        //   new SimpleAuthenticationInfo(user, pwd, this.getName())中的第一个参数的类型需要保持一致        SysUser user = (SysUser)principals.getPrimaryPrincipal();        System.out.println("--------2.用户["+user.getUserName()+"]进行权限验证--------");        // 2.单独定一个集合对象放置角色信息         Set
roles = new HashSet
(); roles.add(user.getRoleName()); // 3.查到权限数据,返回授权信息(要包括 上边的permissions) SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(roles); return simpleAuthorizationInfo; } /** * Overriding * @功能描述: 登陆验证 * @param arg0 * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { System.out.println("---------用户登录验证---------"); // 1.获取登录名称 String userName = token.getPrincipal().toString(); // 2.根据登录名称获取用户信息(从缓存获取,正式项目从数据库) SysUser user = UserCache.getUserCacheMap(userName); if (null == user) { // 抛出账户不存在的异常 throw new UnknownAccountException(); } // 3.获取查询到到密码和盐值 String pwd = user.getPassWord(); String salt = user.getSalt(); // 4.交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配 // new SimpleAuthenticationInfo(user, pwd, this.getName())中的user是SysUser对象,在其他接收的地方也要转成SysUser对象 SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user, pwd, this.getName()); // 设置盐值(salt = pwd+userName + salt) authcInfo.setCredentialsSalt(ByteSource.Util.bytes(pwd+userName + salt)); return authcInfo; }}
2.3 自定义shiro核心配置类(取代xml配置文件)
package com.qfx.demo.shiro;import java.util.LinkedHashMap;import java.util.Map;import javax.servlet.Filter;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.session.mgt.eis.MemorySessionDAO;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.qfx.demo.cache.MenuRoleCache;import com.qfx.demo.vo.SysMenuRole;@Configurationpublic class ShiroConfig {    /**         * 
功能:凭证匹配器
* @return */ @Bean public HashedCredentialsMatcher hashMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); //采用md5加密,没有默认值.可以有MD5或者SHA-1,如果对密码安全有更高要求可以用SHA-256或者更高 hashedCredentialsMatcher.setHashAlgorithmName("md5"); //散列的次数,比如散列2次,相当于md5(md5("")); hashedCredentialsMatcher.setHashIterations(2); //默认是true,true时用的是Hex编码;false时用Base64编码 hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); return hashedCredentialsMatcher; } /** *
功能:配置shiro session 的一个管理器
* @return */ @Bean public DefaultWebSessionManager sessionManager(){ DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); defaultWebSessionManager.setSessionDAO(new MemorySessionDAO()); // 隐藏在地址栏中显示的JSESSIONID defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false); // session的失效时长,单位毫秒(这里设置为30分钟,实际项目请自行修改) defaultWebSessionManager.setGlobalSessionTimeout(1800000); // 间隔一定时间清理失效会话,单位毫秒(这里设置为每5分钟清理一次用户直接关闭浏览器造成的孤立会话,实际项目请自行修改) defaultWebSessionManager.setSessionValidationInterval(300000); // 描session线程,负责清理超时会话 defaultWebSessionManager.setSessionValidationSchedulerEnabled(true); return defaultWebSessionManager; } /** *
功能:自定义realm认证类,继承自AuthorizingRealm,负责用户的认证和权限的处理
* @param hashMatcher * @return */ @Bean public UserRealm userRealm(HashedCredentialsMatcher hashMatcher){ UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(hashMatcher); return userRealm; } /** *
功能:安全管理器
* 权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类 * @param userRealm * @param sessionManager * @return */ @Bean public DefaultWebSecurityManager securityManager(UserRealm userRealm, DefaultWebSessionManager sessionManager){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 自定义realm securityManager.setRealm(userRealm); // shiro 会话管理 securityManager.setSessionManager(sessionManager); return securityManager; } /** *
功能:自定义权限过滤器
* @param securityManager * @return */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 调用我们配置的安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); // 配置我们的登录请求地址,非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射 shiroFilterFactoryBean.setLoginUrl("/view/error/401.jsp"); // 设置无权限时跳转的URL shiroFilterFactoryBean.setUnauthorizedUrl("/view/error/403.jsp"); Map
filter = shiroFilterFactoryBean.getFilters(); filter.put("roles", new CustomRolesAuthorizationFilter()); // 设置拦截器 Map
filterChainDefinitionMap = new LinkedHashMap<>(); shiroFilterFactoryBean.setFilters(filter); // 对静态资源设置匿名访问,从resoutces/static后面开始写 filterChainDefinitionMap.put("/css/**", "anon"); // 可匿名访问的地址 filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/index.jsp", "anon"); filterChainDefinitionMap.put("/login/loginPage", "anon"); filterChainDefinitionMap.put("/login/register", "anon"); filterChainDefinitionMap.put("/login/login", "anon"); // 请求 logout.do地址,shiro去清除session filterChainDefinitionMap.put("/logout", "logout"); //循环url,逐个添加到section中。section就是filterChainDefinitionMap, //里面的键就是链接URL,值就是存在什么条件才能访问该链接 Map
menuRoleMap = MenuRoleCache.menuRoleCacheMap; for (String key : menuRoleMap.keySet()) { filterChainDefinitionMap.put(key, "roles["+menuRoleMap.get(key).getRoleNames()+"]"); } //所有url都必须认证通过才可以访问,必须放在最后 filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }}

3.其他文件

javaBean文件和缓存类等信息就不从这里贴出来了,核心的就是上面的几个文件,想要应用的话,只要把对应的获取数据的地方修改成自己的实现就可以了;或者想要本示例源码的话,请进行下载。

转载于:https://blog.51cto.com/1197822/2298764

你可能感兴趣的文章
字符编码-Unicode等
查看>>
mind map in latex
查看>>
郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(三)SVD...
查看>>
log4j整理
查看>>
Oracle Tuning ( instance 级别 ) 01
查看>>
HTML 5 画布
查看>>
# 20155224 实验四 Android程序设计
查看>>
ARP 协议 理解
查看>>
Allow windows service to "Interact with desktop"
查看>>
InitGoogleLogging坑爹
查看>>
SQL 查询间隔时间大于60s的所有数据
查看>>
*ecshop 限制文章帮助文章显示条数
查看>>
使用phpStudyy运行tipask
查看>>
c# 常用函数
查看>>
网络TCp数据的传输设计(黏包处理)
查看>>
C++ Custom Control控件 向父窗体发送对应的消息
查看>>
二十四 多重继承
查看>>
jmeter压力性能测试-多台机器并发请求
查看>>
选择编程字体
查看>>
小程序日常工作总结
查看>>