SpringBoot配置shiro安全框架的实现

网友投稿 260 2023-01-19

SpringBoot配置shiro安全框架的实现

首先引入pom

org.springframework.boot

spring-boot-starter-parent

2.1.0.RELEASE

org.apache.shiro

shiro-core

${shiro.version}

org.apache.shiro

shiro-web

${shiro.version}

org.apache.shiro

shiro-spring

${shiro.version}

org.crazycake

shiro-redis

3.1.0

net.mingsoft

shiro-freemarker-tags

1.0.0

org.springframework.boot

spring-boot-starter-freemarker

ShiroConfig.java

package com.jx.cert.web.framework.config.shiro;

import java.util.LinkedHashMap;

import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

import org.apache.shiro.cache.MemoryConstrainedCacheManager;

import org.apache.shiro.mgt.SecurityManager;

import org.apache.shiro.session.mgt.SessionManager;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.crazycake.shiro.RedisCacheManager;

import org.crazycake.shiro.RedisManager;

import org.crazycake.shiro.RedisSessionDAO;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.DependsOn;

import com.jx.cert.web.framework.config.shiro.filter.KickoutSessionControlFilter;

import com.jx.cert.web.framework.config.shiro.filter.ShiroPermissionsFilter;

import com.jx.cert.web.framework.config.shiro.filter.SystemLogoutFilter;

import com.jx.common.utils.CacheConstants;

/**

* @ClassName: gyu

* @Description: TODO(shrio配置)

* @author gangyu

* @date 2018年12月4日 下午2:28:07

*/

@Configuration

public class ShiroConfig {

Logger log=LoggerFactory.getLogger(ShiroConfig.class);

@Value("${spring.redis.host}")

private String host;

@Value("${spring.redis.prot}")

private int port;

@Value("${spring.redis.timeout}")

private int timeout;

@Value("${spring.redis.password}")

private String password;

@Value("${spring.redis.database}")

private int database;

//注意这里需要设置成 static 否则 @Value 注入不了数据

@Bean(name = "lifecycleBeanPostProcessor")

public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {

return new LifecycleBeanPostProcessor();

}

@Bean(name = "shiroFilter")

public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

log.debug("-----------------Shiro拦截器工厂类注入开始");

Map filterMap=shiroFilterFactoryBean.getFilters();

//权限过滤器

filterMap.put("perms", new ShiroPermissionsFilter());

shiroFilterFactoryBean.setFilters(filterMap);

// 配置shiro安全管理器 SecurityManager

shiroFilterFactoryBean.setSecurityManager(securityManager);

// 指定要求登录时的链接

shiroFilterFactoryBean.setLoginUrl("/login");

// 登录成功后要跳转的链接

shiroFilterFactoryBean.setSuccessUrl("/index");

// filterChainDefinitions拦截器=map必须用:LinkedHashMap,因为它必须保证有序

Map filterChainDefinitionMap = new LinkedHashMap();

//对外应用开发接口不验证

filterChainDefinitionMap.put("/app/**", "anon");

filterChainDefinitionMap.put("/ajaxLogin", "anon");

// 放开验证码

filterChainDefinitionMap.put("/public/getGifCode", "anon");

// 退出

filterChainDefinitionMap.put("/logout", "logout");

//TODO 全部放行

// filterChainDefinitionMap.put("/manage/**", "anon[*]");

//公共资源

filterChainDefinitionMap.put("/static/**", "anon");

filterChainDefinitionMap.put("/css/**", "anon");

filterChainDefinitionMap.put("/img/**", "anon");

filterChainDefinitionMap.put("/js/**", "anon");

// authc:所有url都必须认证通过才可以访问;

filterChainDefinitionMap.put("/**", "authc");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

log.debug("-----------------Shiro拦截器工厂类注入成功");

return shiroFilterFactoryBean;

}

@Bean

public HashedCredentialsMatcher hashedCredentialsMatcher() {

HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

hashedCredentialsMatcher.setHashAlgorithmName("MD5");//散列算法:这里使用MD5算法;

hashedCredentialsMatcher.setHashIterations(1);//散列的次数,比如散列两次,相当于 md5(md5(""));

return hashedCredentialsMatcher;

}

//权限缓存到内存

@Bean(name = "shiroRealm")

@DependsOn("lifecycleBeanPostProcessor")

public MyShiroRealm myShiroRealm() {

MyShiroRealm myShiroRealm = new MyShiroRealm();

myShiroRealm.setCacheManager(new MemoryConstrainedCacheManager());

myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());

return myShiroRealm;

}

@Bean(name = "securityManager")

public SecurityManager securityManager() {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

securityManager.setRealm(myShiroRealm());

// 自定义session管理 使用redis

securityManager.setSessionManager(sessionManager());

// 自定义缓存实现 使用redis

securityManager.setCacheManager(cacheManager());

return securityManager;

}

/**

* 配置shiro redisManager

* @return

*/

public RedisManager redisManager() {

RedisManager redisManager = new RedisManager();

redisManager.setHost(host);

redisManager.setPort(port);

redisManager.setTimeout(timeout);

// redisManager.setPassword(password);

redisManager.setDatabase(database);

return redisManager;

}

//自定义sessionManager

@Bean

public SessionManager sessionManager() {

MySessionManager mySessionManager = new MySessionManager();

mySessionManager.setSessionDAO(redisSessionDAO());

//默认1个小时session过期

mySessionManager.setGlobalSessionTimeout(CacheConstants.SHIRO_SESSION_MS);

return mySessionManager;

}

/**

* RedisSessionDAO shiro sessionDao层的实现 通过redis

*/

@Bean

public RedisSessionDAO redisSessionDAO() {

RedisSessionDAO redisSessionDAO = new RedisSessionDAO();

redisSessionDAO.setRedisManager(redisManager());

return redisSessionDAO;

}

/**

* cacheManager 缓存 redis实现

* @return

*/

@Bean

public RedisCacheManager cacheManager() {

RedisCacheManager redisCacheManager = new RedisCacheManager();

redisCacheManager.setRedisManager(redisManager());

redisCacheManager.setExpire(CacheConstants.USER_DATA_TTL);

return redisCacheManager;

}

}

MyShiroRealm.java

package com.jx.cert.web.framework.config.shiro;

import java.util.ArrayList;

import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.LockedAccountException;

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.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import com.jx.cert.web.framework.config.shiro.exception.SysUsreNotLoginAPPException;

import com.jx.cert.web.framework.config.shiro.exception.SystemNotExistException;

import com.jx.common.utils.SysCode;

import com.jx.core.api.model.vo.cert.SysPermission;

import com.jx.core.api.model.vo.cert.SysRole;

import com.jx.core.api.model.vo.cert.SysSystem;

import com.jx.core.api.model.vo.cert.SysUser;

import com.jx.core.api.service.business.cert.SysPermissionService;

import com.jx.core.api.service.business.cert.SysRoleService;

import com.jx.core.api.service.business.cert.SysSystemService;

import com.jx.core.api.service.business.cert.SysUserService;

public class MyShiroRealm extends AuthorizingRealm {

private Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);

@Autowired

private SysUserService sysUserService;

@Autowired

private SysRoleService sysRoleService;

@Autowired

private SysPermissionService sysPermissionService;

@Autowired

private SysSystemService systemService;

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

logger.info("####################开始配置权限####################");

SysUser user = (SysUser) principals.getPrimaryPrincipal();

if (user != null) {

//权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)

SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

List roleStrlist = new ArrayList();//用户的角色集合

List perminsStrlist = new ArrayList();//用户的菜单权限集合

for (SysRole role : user.getRoleList()) {

roleStrlist.add(role.getRoleName());

}

for (SysPermission permission : user.getPermissList()) {

perminsStrlist.add(permission.getUrl());

}

//用户的角色集合

authorizationInfo.addRoles(roleStrlist);

//用户的菜单按钮权限集合

authorizationInfo.addStringPermissions(perminsStrlist);

return authorizationInfo;

}

return null;

}

/*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)

throws AuthenticationException {

logger.info("####################身份认证####################");

String userStr = (String) token.getPrincipal();

SysUser user = sysUserService.getUserByUserName(userName);

//认证系统用户

List roleList = sysRoleService.findRoleByUserId(user.getUserId(),systemId);

user.setRoleList(roleList);//获取用户角色

List list=sysPermissionService.getUserPermission(user.getUserId(),systemId);

SysPermission permis=new SysPermission();

list.add(permis);

user.setPermissList(list);//获取用户权限

return new SimpleAuthenticationInfo(user, DigestUtils.md5Hex(user.getPassword()),getName());

}

}

ShiroTagsFreeMarkerCfg.java

package com.jx.cert.web.framework.config.shiro;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.jagregory.shiro.freemarker.ShiroTags;

import freemarker.template.TemplateModelException;

/**

* @ClassName: ShiroTagsFreeMarkerCfg

* @Description: TODO(ftl shiro 标签)

* @author gangyu

* @date 2018年12月5日 下午5:16:27

*

*/

@Component

public class ShiroTagsFreeMarkerCfg {

@Autowired

private FreeMarkerConfigurer freeMarkerConfigurer;

@PostConstruct

public void setSharedVariable() throws TemplateModelException {

freeMarkerConfigurer.getConfiguration().setSharedVariable("shiro", new ShiroTags());

}

}

ShiroPermissionsFilter.java

/**

* @Title: ShiroPermissionsFilter.java

* @Package com.jx.cert.web.config.shiro

* @Description: TODO(用一句话描述该文件做什么)

* @author gangyu

* @date 2018年12月5日 上午11:47:00

* @version V1.0

*/

package com.jx.cert.web.framework.config.shiro.filter;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

import com.jx.cert.web.framework.config.shiro.ShiroUtil;

import com.jx.common.utils.Result;

import com.jx.common.utils.enums.CodeEnum;

import com.jx.core.api.model.vo.cert.SysPermission;

import com.jx.core.api.model.vo.cert.SysUser;

/**

* @ClassName: ShiroPermissionsFilter

* @Description: TODO(权限验证)

* @author gangyu

* @date 2018年12月5日 上午11:47:00

*/

public class ShiroPermissionsFilter extends PermissionsAuthorizationFilter {

private static final Logger logger = LoggerFactory.getLogger(ShiroPermissionsFilter.class);

/**

* 权限检测验证

*/

@Override

protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {

logger.info("----------权限校验-------------");

HttpServletRequest request = (HttpServletRequest) servletRequest;

HttpServletResponse response = (HttpServletResponse) servletResponse;

String reqUrl=request.getRequestURI();

List permsList=ShiroUtil.getUser().getPermissList();

String contextPath=request.getContextPath();

reqUrl=reqUrl.substring(contextPath.length()+1, reqUrl.length());

String header = request.getHeader("X-Requested-With");

boolean isAjax = "XMLHttpRequest".equals(header);

SysUser user=ShiroUtil.getUser();

if(!new Gson().toJson(permsList).contains(reqUrl)){

if (isAjax) {

logger.info("----------AJAX请求拒绝-------------");

response.setCharacterEncoding("UTF-8");

response.setContentType("application/json");

response.getWriter().write(new Gson().toJson(new Result(CodeEnum.NOT_PERMISSION)));

} else {

logger.info("----------普通请求拒绝-------------");

response.sendRedirect(request.getContextPath()+"/403");

}

return false;

}else {

return true;

}

}

}

ShiroUtil.java

package com.jx.cert.web.framework.config.shiro;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.session.Session;

import org.apache.shiro.subject.Subject;

import com.jx.core.api.model.vo.cert.SysUser;

public class ShiroUtil {

/**

* 获取当前 Subject

*

* @return

*/

public static Subject getSubject() {

return SecurityUtils.getSubject();

}

/**

* 获取shiro指定的sessionKey

*

* @param key

* @param

* @return

*/

public static T getSessionAttr(String key) {

Session session = getSession();

return session != null ? (T) session.getAttribute(key) : null;

}

/**

* 设置shiro指定的sessionKey

*

* @param key

* @param value

*/

public static void setSessionAttr(String key, Object value) {

Session session = getSession();

session.setAttribute(key, value);

}

/**

* 获取当前用户对象

*

* @return

*/

public static SysUser getUser() {

if(getSubject().isAuthenticated()){

return (SysUser) getSubject().getPrincipals().getPrimaryPrincipal();

}

return null;

}

/**

* 获取当前用户对象UserID

*

* @return

*/

public static String getUserId() {

return getUser().getUserId();

}

/**

* 移除shiro指定的sessionKey

*

* @param key

*/

public static void removeSessionAttr(String key) {

Session session = getSession();

if (session != null)

session.removeAttribute(key);

}

/**

* 验证当前用户是否属于该角色

*

* @param roleName 角色名称

* @return 属于该角色:true,否则false

*/

public static boolean hasRole(String roleName) {

return getSubject() != null && roleName != null

&& roleName.length() > 0 && getSubject().hasRole(roleName);

}

/**

* shiro 中获取session

*

* @return session

*/

public static Session getSession() {

return getSubject().getSession();

}

/**

* 验证当前用户是否属于以下所有角色

* 多权限“,”分割

*

* @param roleNames 权限名称

* @return 属于:true,否则false

*/

public static boolean hasAllRoles(String roleNames) {

boolean hasAllRole = true;

Subject subject = getSubject();

if (subject != null && roleNames != null && roleNames.length() > 0) {

for (String role : roleNames.split(",")) {

if (!subject.hasRole(role.trim())) {

hasAllRole = false;

break;

}

}

}

return hasAllRole;

}

/**

* 验证当前用户是否属于以下任意一个角色

* 多权限“,”分割

* @param rohttp://leNames

* @return

*/

public static boolean hasAnyRoles(String roleNames) {

boolean hasAnyRole = false;

Subject subject = getSubject();

if (subject != null && roleNames != null && roleNames.length() > 0) {

for (String role : roleNames.split(",")) {

if (subject.hasRole(role.trim())) {

hasAnyRole = true;

break;

}

}

}

return hasAnyRole;

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Mybatis一级缓存和结合Spring Framework后失效的源码探究
下一篇:小说开放api接口(小说api开发接口)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~