- 配置文件
package io.renren.common.config
import io.renren.modules.sys.shiro.RedisShiroSessionDAO
import io.renren.modules.sys.shiro.UserRealm
import org.apache.shiro.mgt.SecurityManager
import org.apache.shiro.session.mgt.SessionManager
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.web.session.mgt.DefaultWebSessionManager
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.LinkedHashMap
import java.util.Map
@Configuration
public class ShiroConfig {
@Bean("sessionManager")
public SessionManager sessionManager(RedisShiroSessionDAO redisShiroSessionDAO,
@Value("${renren.redis.open}") boolean redisOpen,
@Value("${renren.shiro.redis}") boolean shiroRedis){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager()
//设置session过期时间为1小时(单位:毫秒),默认为30分钟
sessionManager.setGlobalSessionTimeout(60 * 60 * 1000)
sessionManager.setSessionValidationSchedulerEnabled(true)
sessionManager.setSessionIdUrlRewritingEnabled(false)
//如果开启redis缓存且renren.shiro.redis=true,则shiro session存到redis里
if(redisOpen && shiroRedis){
sessionManager.setSessionDAO(redisShiroSessionDAO)
}
return sessionManager
}
@Bean("securityManager")
public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager()
securityManager.setRealm(userRealm)
securityManager.setSessionManager(sessionManager)
return securityManager
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean()
shiroFilter.setSecurityManager(securityManager)
shiroFilter.setLoginUrl("/login.html")
shiroFilter.setUnauthorizedUrl("/")
Map<String, String> filterMap = new LinkedHashMap<>()
filterMap.put("/swagger/**", "anon")
filterMap.put("/v2/api-docs", "anon")
filterMap.put("/swagger-ui.html", "anon")
filterMap.put("/webjars/**", "anon")
filterMap.put("/swagger-resources/**", "anon")
filterMap.put("/statics/**", "anon")
filterMap.put("/login.html", "anon")
filterMap.put("/sys/login", "anon")
filterMap.put("/favicon.ico", "anon")
filterMap.put("/captcha.jpg", "anon")
filterMap.put("/**", "authc")
shiroFilter.setFilterChainDefinitionMap(filterMap)
return shiroFilter
}
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor()
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator()
proxyCreator.setProxyTargetClass(true)
return proxyCreator
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor()
advisor.setSecurityManager(securityManager)
return advisor
}
}
- session redis持久化
/**
* Copyright 2018 人人开源 http://www.renren.io
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.renren.modules.sys.shiro;
import io.renren.common.utils.RedisKeys;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.concurrent.TimeUnit;
/**
* shiro session dao
*
* @author chenshun
* @email [email protected]
* @date 2017/9/27 21:35
*/
@Component
public class RedisShiroSessionDAO extends EnterpriseCacheSessionDAO {
@Autowired
private RedisTemplate redisTemplate;
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = super.doCreate(session);
final String key = RedisKeys.getShiroSessionKey(sessionId.toString());
setShiroSession(key, session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
Session session = super.doReadSession(sessionId);
if(session == null){
final String key = RedisKeys.getShiroSessionKey(sessionId.toString());
session = getShiroSession(key);
}
return session;
}
@Override
protected void doUpdate(Session session) {
super.doUpdate(session);
final String key = RedisKeys.getShiroSessionKey(session.getId().toString());
setShiroSession(key, session);
}
@Override
protected void doDelete(Session session) {
super.doDelete(session);
final String key = RedisKeys.getShiroSessionKey(session.getId().toString());
redisTemplate.delete(key);
}
private Session getShiroSession(String key) {
return (Session)redisTemplate.opsForValue().get(key);
}
private void setShiroSession(String key, Session session){
redisTemplate.opsForValue().set(key, session);
redisTemplate.expire(key, 60, TimeUnit.MINUTES);
}
}
- xml过滤器配置
/**
* Copyright 2018 人人开源 http://www.renren.io
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.renren.common.config;
import io.renren.common.xss.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.DispatcherType;
/**
* Filter配置
*
* @author Mark [email protected]
* @since 2.1.0 2017-04-21
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean shiroFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
registration.addInitParameter("targetFilterLifecycle", "true");
registration.setEnabled(true);
registration.setOrder(Integer.MAX_VALUE - 1);
registration.addUrlPatterns("/*");
return registration;
}
@Bean
public FilterRegistrationBean xssFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}
- 自定义realm
/**
* Copyright 2018 人人开源 http://www.renren.io
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.renren.modules.sys.shiro;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import io.renren.common.utils.Constant;
import io.renren.modules.sys.entity.SysUserEntity;
import io.renren.modules.sys.dao.SysMenuDao;
import io.renren.modules.sys.dao.SysUserDao;
import io.renren.modules.sys.entity.SysMenuEntity;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 认证
*
* @author chenshun
* @email [email protected]
* @date 2016年11月10日 上午11:55:49
*/
@Component
public class UserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
@Autowired
private SysMenuDao sysMenuDao;
/**
* 授权(验证权限时调用)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
Long userId = user.getUserId();
List<String> permsList;
if(userId == Constant.SUPER_ADMIN){
List<SysMenuEntity> menuList = sysMenuDao.selectList(null);
permsList = new ArrayList<>(menuList.size());
for(SysMenuEntity menu : menuList){
permsList.add(menu.getPerms());
}
}else{
permsList = sysUserDao.queryAllPerms(userId);
}
Set<String> permsSet = new HashSet<>();
for(String perms : permsList){
if(StringUtils.isBlank(perms)){
continue;
}
permsSet.addAll(Arrays.asList(perms.trim().split(",")));
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setStringPermissions(permsSet);
return info;
}
/**
* 认证(登录时调用)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
SysUserEntity user = new SysUserEntity();
user.setUsername(token.getUsername());
user = sysUserDao.selectOne(user);
if(user == null) {
throw new UnknownAccountException("账号或密码不正确");
}
if(user.getStatus() == 0){
throw new LockedAccountException("账号已被锁定,请联系管理员");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
return info;
}
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.hashAlgorithmName);
shaCredentialsMatcher.setHashIterations(ShiroUtils.hashIterations);
super.setCredentialsMatcher(shaCredentialsMatcher);
}
}