springBoot整合shiro,realm和config文件编写

1. Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;

也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource , 即安全数据源。

package com.javon.boot.realm;


import com.javon.boot.service.UserService;
import com.javon.boot.vo.SysUser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.apache.shiro.util.ByteSource;

import javax.annotation.Resource;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {
	private Log log = LogFactory.getLog(UserRealm.class);
	@Resource
	private UserService userService;

	@SuppressWarnings("unchecked")
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String username = (String) principals.getPrimaryPrincipal();
		Set<String> allRoles = userService.findRoles(username);
		Set<String> allResources = userService.findPermissions(username);
		if(allRoles.isEmpty()||allResources.isEmpty()){
			log.error("未找到用户:"+username+"授权信息!");
		}
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		authorizationInfo.setRoles(allRoles);
		authorizationInfo.setStringPermissions(allResources);
		return authorizationInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String username = (String) token.getPrincipal();
		SysUser user =userService.getByUserName(username);
		if (user == null) {
			log.info(username+"没找到帐号");
			throw new UnknownAccountException();// 没找到帐号
		}
		if (user.getLocked()==1) {
			log.info(username+"帐号锁定");
			throw new LockedAccountException(); // 帐号锁定
		}
		// 密码验证
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(), // 用户名
				user.getPassword(), // 密码
				ByteSource.Util.bytes(user.getCredentialsSalt()), // salt=username+salt
				getName() // realm name
		);
		return authenticationInfo;
	}

	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		super.clearCachedAuthorizationInfo(principals);
	}

	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		super.clearCache(principals);
	}

	public void clearAllCachedAuthorizationInfo() {
		getAuthorizationCache().clear();
	}

	public void clearAllCachedAuthenticationInfo() {
		getAuthenticationCache().clear();
	}

	public void clearAllCache() {
		clearAllCachedAuthenticationInfo();
		clearAllCachedAuthorizationInfo();
	}

}

2.最重要的shiroconfig文件编写

package com.javon.boot.config;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler;
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.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import com.javon.boot.realm.UserRealm;
import com.javon.boot.util.KickoutSessionControlFilter;
import com.javon.boot.util.RetryLimitHashedCredentialsMatcher;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.springframework.web.filter.DelegatingFilterProxy;

@Configuration
public class ShiroConfig {
	@Bean
	public UserRealm getRealm() {// 1、获取配置的Realm,之所以没使用注解配置,是因为此处需要考虑到加密处理
		UserRealm realm = new UserRealm();
		realm.setCredentialsMatcher(getRetryLimitHashedCredentialsMatcher());
		realm.setCacheManager(getCacheManager());
		realm.setCachingEnabled(false);
		return realm;
	}

	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
		daap.setProxyTargetClass(true);
		return daap;
	}

	@Bean
	public EhCacheManager getCacheManager() {// 2、缓存配置
		EhCacheManager cacheManager = new EhCacheManager();
		cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
		return cacheManager;
	}

	/*
	 * @Bean public HashedCredentialsMatcher getHashedCredentialsMatcher() {//
	 * 认证bean配置 HashedCredentialsMatcher credentialsMatcher = new
	 * HashedCredentialsMatcher();
	 * credentialsMatcher.setHashAlgorithmName("md5");
	 * credentialsMatcher.setHashIterations(2);
	 * credentialsMatcher.setStoredCredentialsHexEncoded(true); return
	 * credentialsMatcher; }
	 */
	@Bean // 登录次数限制
	public RetryLimitHashedCredentialsMatcher getRetryLimitHashedCredentialsMatcher() {
		RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(
				getCacheManager());
		retryLimitHashedCredentialsMatcher.setHashAlgorithmName("md5");
		retryLimitHashedCredentialsMatcher.setHashIterations(2);
		retryLimitHashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
		return retryLimitHashedCredentialsMatcher;
	}

	// 登录并发控制
	public KickoutSessionControlFilter getKickoutSessionControlFilter(SessionManager sessionManager) {
		KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
		kickoutSessionControlFilter.setCacheManager(getCacheManager());
		kickoutSessionControlFilter.setSessionManager(sessionManager);
		kickoutSessionControlFilter.setKickoutAfter(false);
		kickoutSessionControlFilter.setMaxSession(1);
		kickoutSessionControlFilter.setKickoutUrl("/login?kickout=1");
		return kickoutSessionControlFilter;
	}

	// 配置此bean才能结合thymeleaf使用shiro页面标签语法
	@Bean
	public ShiroDialect getShiroDialect() {
		return new ShiroDialect();
	}

	@Bean
	public SessionIdGenerator getSessionIdGenerator() { // 3
		return new JavaUuidSessionIdGenerator();
	}

	@Bean
	public SessionDAO getSessionDAO(SessionIdGenerator sessionIdGenerator) { // 4
		EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
		sessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
		sessionDAO.setSessionIdGenerator(sessionIdGenerator);
		return sessionDAO;
	}

	@Bean
	public QuartzSessionValidationScheduler getQuartzSessionValidationScheduler() {
		QuartzSessionValidationScheduler sessionValidationScheduler = new QuartzSessionValidationScheduler();
		sessionValidationScheduler.setSessionValidationInterval(100000);
		return sessionValidationScheduler;
	}

	@Bean
	public RememberMeManager getRememberManager() { // 5
		CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
		SimpleCookie cookie = new SimpleCookie("SysUser-RememberMe");
		cookie.setHttpOnly(true);
		cookie.setMaxAge(3600);
		rememberMeManager.setCookie(cookie);
		return rememberMeManager;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
			DefaultWebSecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
		aasa.setSecurityManager(securityManager);
		return aasa;
	}

	@Bean
	public DefaultWebSessionManager getSessionManager(SessionDAO sessionDAO) { // 6
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(1000000);
		sessionManager.setDeleteInvalidSessions(true);
		sessionManager.setSessionValidationSchedulerEnabled(true);
		sessionManager.setSessionDAO(sessionDAO);
		SimpleCookie sessionIdCookie = new SimpleCookie("sid");
		sessionIdCookie.setHttpOnly(true);
		sessionIdCookie.setMaxAge(-1);
		sessionManager.setSessionIdCookie(sessionIdCookie);
		sessionManager.setSessionIdCookieEnabled(true);
		return sessionManager;
	}

	@Bean
	public DefaultWebSecurityManager getSecurityManager(Realm userRealm, EhCacheManager cacheManager,
			SessionManager sessionManager, RememberMeManager rememberMeManager) {// 7
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(userRealm);
		securityManager.setCacheManager(getCacheManager());
		securityManager.setSessionManager(sessionManager);
		securityManager.setRememberMeManager(rememberMeManager);
		return securityManager;
	}

	public FormAuthenticationFilter getLoginFilter() { // 在ShiroFilterFactoryBean中使用
		FormAuthenticationFilter filter = new FormAuthenticationFilter();
		filter.setUsernameParam("username");
		filter.setPasswordParam("password");
		// filter.setRememberMeParam("rememberMe");
		filter.setLoginUrl("/login"); // 登录提交页面
		filter.setFailureKeyAttribute("shiroLoginFailure");// 登录失败提示信息
		return filter;
	}

	public LogoutFilter getLogoutFilter() { // 在ShiroFilterFactoryBean中使用
		LogoutFilter logoutFilter = new LogoutFilter();
		logoutFilter.setRedirectUrl("/login"); // 首页路径,登录注销后回到的页面
		return logoutFilter;
	}
	/*
	用于解决监听当前登录用户信息报错
	org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
	 */
	@Bean
	public FilterRegistrationBean delegatingFilterProxy(){
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		DelegatingFilterProxy proxy = new DelegatingFilterProxy();
		proxy.setTargetFilterLifecycle(true);
		proxy.setTargetBeanName("shiroFilter");
		filterRegistrationBean.setFilter(proxy);
		return filterRegistrationBean;
	}

	/**
	 * 监听当前登录用户信息
	 * @return
	 */
	@Bean
	public SysUserFilterConfig getSysUserFilterConfig(){
		return new SysUserFilterConfig();
	}
	@Bean("shiroFilter")
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		shiroFilterFactoryBean.setLoginUrl("/login"); // 设置登录页路径
		shiroFilterFactoryBean.setSuccessUrl("/index"); // 设置跳转成功页
		shiroFilterFactoryBean.setUnauthorizedUrl("/pages/unauthUrl"); // 授权错误页
		Map<String, Filter> filters = new HashMap<String, Filter>();
		filters.put("authc", this.getLoginFilter());
		filters.put("logout", this.getLogoutFilter());
		//添加获取当前登录用户filter
		filters.put("sysUser", getSysUserFilterConfig());
		// 登录并发拦截
		filters.put("kickout", this.getKickoutSessionControlFilter(securityManager.getSessionManager()));
		shiroFilterFactoryBean.setFilters(filters);
		Map<String, String> filterChainDefinitionMap = new HashMap<String, String>();
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/login", "authc"); // 定义内置登录处理
		filterChainDefinitionMap.put("/css/**", "anon");
		filterChainDefinitionMap.put("/js/**", "anon");
		filterChainDefinitionMap.put("/fonts/**", "anon");
		filterChainDefinitionMap.put("/img/**", "anon");
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/kickout", "authc");
		filterChainDefinitionMap.put("/**", "kickout,authc,sysUser");// 请求拦截路径
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}
}

如需登录次数限制,用户踢出,和当前用户拦截源码,留言获取

猜你喜欢

转载自blog.csdn.net/wjw1639942939/article/details/80347245