first commit

This commit is contained in:
ouburikou
2018-02-05 18:59:21 +08:00
commit bb00973025
957 changed files with 231677 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shiro-springboot-demo</artifactId>
<groupId>demo.xinwin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot-shiro-configure</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>${shiro.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- @ConfigurationProperties annotation processing (metadata for IDEs) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,44 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* This guy is lazy, nothing left.
*
* @author 张劲航
*/
public class FormSignInFilter extends FormAuthenticationFilter {
@Override
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
request.setAttribute(getFailureKeyAttribute(), ae);
}
@Override
protected void redirectToLogin(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {
try {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String contentType = request.getContentType();
if (contentType != null && contentType.contains("application/json")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
writer.print("{\"error\":\"登录超时,请重新登录。\"}");
} else {
super.redirectToLogin(servletRequest, servletResponse);
}
} catch (Exception e) {
e.printStackTrace();
super.redirectToLogin(servletRequest, servletResponse);
}
}
}

View File

@@ -0,0 +1,55 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
private Cache<String, AtomicInteger> passwordRetryCache;
private int retryMax = 5;
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
}
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws ExcessiveAttemptsException {
String username = (String)token.getPrincipal();
AtomicInteger retryCount = passwordRetryCache.get(username);
if(retryCount == null) {
retryCount = new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if(retryCount.incrementAndGet() > retryMax) {
throw new ExcessiveAttemptsException("您已连续错误达" + retryMax + "请10分钟后再试");
}
boolean matches = super.doCredentialsMatch(token, info);
if(matches) {
passwordRetryCache.remove(username);
}else {
throw new IncorrectCredentialsException("密码错误,已错误" + retryCount.get() + "次,最多错误" + retryMax + "");
}
return true;
}
public int getRetryMax() {
return retryMax;
}
public void setRetryMax(int retryMax) {
this.retryMax = retryMax;
}
}

View File

@@ -0,0 +1,278 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.crypto.CipherService;
import org.apache.shiro.io.Serializer;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
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.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import com.xinwei.spring.boot.autoconfigure.shiro.annotation.EnableShiroWebSupport;
import javax.servlet.Filter;
import javax.sql.DataSource;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
@Configuration
@EnableShiroWebSupport
@ConditionalOnWebApplication
@Import(ShiroConfiguration.class)
@EnableConfigurationProperties({
ShiroProperties.class, ShiroSignInProperties.class,
ShiroCookieProperties.class, ShiroSessionProperties.class,
ShiroJdbcRealmProperties.class
})
public class ShiroAutoConfiguration {
@Autowired
private ShiroProperties properties;
@Autowired
private ShiroSignInProperties signInProperties;
@Autowired
private ShiroCookieProperties shiroCookieProperties;
@Autowired
private ShiroSessionProperties shiroSessionProperties;
@Autowired
private ShiroJdbcRealmProperties shiroJdbcRealmProperties;
@Autowired(required = false)
private CipherService cipherService;
@Autowired(required = false)
private Serializer<PrincipalCollection> serializer;
@Autowired(required = false)
private Collection<SessionListener> listeners;
@Bean(name = "mainRealm")
@ConditionalOnMissingBean(name = "mainRealm")
@ConditionalOnProperty(prefix = "shiro.realm.jdbc", name = "enabled", havingValue = "true")
@DependsOn(value = {"dataSource", "lifecycleBeanPostProcessor", "credentialsMatcher"})
public Realm jdbcRealm(DataSource dataSource, CredentialsMatcher credentialsMatcher) {
JdbcRealm jdbcRealm = new JdbcRealm();
if (shiroJdbcRealmProperties.getAuthenticationQuery() != null) {
jdbcRealm.setAuthenticationQuery(shiroJdbcRealmProperties.getAuthenticationQuery());
}
if (shiroJdbcRealmProperties.getUserRolesQuery() != null) {
jdbcRealm.setUserRolesQuery(shiroJdbcRealmProperties.getUserRolesQuery());
}
if (shiroJdbcRealmProperties.getPermissionsQuery() != null) {
jdbcRealm.setPermissionsQuery(shiroJdbcRealmProperties.getPermissionsQuery());
}
if (shiroJdbcRealmProperties.getSalt() != null) {
jdbcRealm.setSaltStyle(shiroJdbcRealmProperties.getSalt());
}
jdbcRealm.setDataSource(dataSource);
jdbcRealm.setCredentialsMatcher(credentialsMatcher);
return jdbcRealm;
}
@Bean(name = "mainRealm")
@ConditionalOnMissingBean(name = "mainRealm")
@DependsOn(value = {"lifecycleBeanPostProcessor", "credentialsMatcher"})
public Realm realm(CredentialsMatcher credentialsMatcher) {
Class<?> realmClass = properties.getRealmClass();
Realm realm = (Realm) BeanUtils.instantiate(realmClass);
if (realm instanceof AuthenticatingRealm) {
((AuthenticatingRealm) realm).setCredentialsMatcher(credentialsMatcher);
}
return realm;
}
@Bean(name = "shiroCacheManager")
@ConditionalOnClass(name = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
@ConditionalOnMissingBean(name = "shiroCacheManager")
public CacheManager ehcacheManager() {
EhCacheManager ehCacheManager = new EhCacheManager();
ShiroProperties.Ehcache ehcache = properties.getEhcache();
if (ehcache.getCacheManagerConfigFile() != null) {
ehCacheManager.setCacheManagerConfigFile(ehcache.getCacheManagerConfigFile());
}
return ehCacheManager;
}
@Bean
@ConditionalOnMissingBean(Cookie.class)
public Cookie rememberMeCookie() {
SimpleCookie rememberMeCookie = new SimpleCookie();
rememberMeCookie.setName(signInProperties.getRememberMeParam());
rememberMeCookie.setMaxAge(shiroCookieProperties.getMaxAge());
rememberMeCookie.setValue(shiroCookieProperties.getValue());
rememberMeCookie.setVersion(shiroCookieProperties.getVersion());
rememberMeCookie.setHttpOnly(shiroCookieProperties.isHttpOnly());
rememberMeCookie.setSecure(shiroCookieProperties.isSecure());
return rememberMeCookie;
}
@Bean
@ConditionalOnMissingBean(RememberMeManager.class)
public RememberMeManager rememberMeManager(Cookie cookie) {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(cookie);
cookieRememberMeManager.setCipherService(cipherService);
if (shiroCookieProperties.getCipherKey() != null) {
cookieRememberMeManager.setCipherKey(shiroCookieProperties.getCipherKey().getBytes());
} else {
if (shiroCookieProperties.getEncryptionCipherKey() != null) {
cookieRememberMeManager.setEncryptionCipherKey(shiroCookieProperties.getEncryptionCipherKey().getBytes());
}
if (shiroCookieProperties.getDecryptionCipherKey() != null) {
cookieRememberMeManager.setDecryptionCipherKey(shiroCookieProperties.getDecryptionCipherKey().getBytes());
}
}
cookieRememberMeManager.setSerializer(serializer);
return cookieRememberMeManager;
}
@Bean
@ConditionalOnMissingBean
public SessionDAO sessionDAO(CacheManager cacheManager) {
EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
sessionDAO.setActiveSessionsCacheName(shiroSessionProperties.getActiveSessionsCacheName());
Class<? extends SessionIdGenerator> idGenerator = shiroSessionProperties.getIdGenerator();
if (idGenerator != null) {
SessionIdGenerator sessionIdGenerator = BeanUtils.instantiate(idGenerator);
sessionDAO.setSessionIdGenerator(sessionIdGenerator);
}
sessionDAO.setCacheManager(cacheManager);
return sessionDAO;
}
@Bean(name = "sessionValidationScheduler")
@DependsOn(value = {"sessionManager"})
@ConditionalOnClass(name = {"org.quartz.Scheduler"})
@ConditionalOnMissingBean(SessionValidationScheduler.class)
public SessionValidationScheduler quartzSessionValidationScheduler(DefaultWebSessionManager sessionManager) {
QuartzSessionValidationScheduler quartzSessionValidationScheduler = new QuartzSessionValidationScheduler(sessionManager);
quartzSessionValidationScheduler.setSessionValidationInterval(shiroSessionProperties.getValidationInterval());
quartzSessionValidationScheduler.enableSessionValidation();
sessionManager.setDeleteInvalidSessions(shiroSessionProperties.isDeleteInvalidSessions());
sessionManager.setSessionValidationInterval(shiroSessionProperties.getValidationInterval());
sessionManager.setSessionValidationSchedulerEnabled(shiroSessionProperties.isValidationSchedulerEnabled());
sessionManager.setSessionValidationScheduler(quartzSessionValidationScheduler);
return quartzSessionValidationScheduler;
}
@Bean(name = "sessionValidationScheduler")
@DependsOn(value = {"sessionManager"})
@ConditionalOnMissingBean(SessionValidationScheduler.class)
public SessionValidationScheduler sessionValidationScheduler(DefaultWebSessionManager sessionManager) {
ExecutorServiceSessionValidationScheduler validationScheduler = new ExecutorServiceSessionValidationScheduler(sessionManager);
sessionManager.setDeleteInvalidSessions(shiroSessionProperties.isDeleteInvalidSessions());
sessionManager.setSessionValidationInterval(shiroSessionProperties.getValidationInterval());
sessionManager.setSessionValidationSchedulerEnabled(shiroSessionProperties.isValidationSchedulerEnabled());
sessionManager.setSessionValidationScheduler(validationScheduler);
return validationScheduler;
}
@Bean
@DependsOn(value = {"shiroCacheManager", "sessionDAO"})
public WebSessionManager sessionManager(CacheManager cacheManager, SessionDAO sessionDAO) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(cacheManager);
sessionManager.setGlobalSessionTimeout(shiroSessionProperties.getGlobalSessionTimeout());
sessionManager.setSessionDAO(sessionDAO);
sessionManager.setSessionListeners(listeners);
return sessionManager;
}
@Bean(name = "credentialsMatcher")
@ConditionalOnMissingBean
@DependsOn("shiroCacheManager")
public CredentialsMatcher credentialsMatcher(CacheManager cacheManager) {
RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(cacheManager);
credentialsMatcher.setHashAlgorithmName(properties.getHashAlgorithmName());
credentialsMatcher.setHashIterations(properties.getHashIterations());
credentialsMatcher.setStoredCredentialsHexEncoded(properties.isStoredCredentialsHexEncoded());
credentialsMatcher.setRetryMax(properties.getRetryMax());
return credentialsMatcher;
}
public FormSignInFilter formSignInFilter() {
FormSignInFilter filter = new FormSignInFilter();
filter.setLoginUrl(properties.getLoginUrl());
filter.setSuccessUrl(properties.getSuccessUrl());
filter.setUsernameParam(signInProperties.getUserParam());
filter.setPasswordParam(signInProperties.getPasswordParam());
filter.setRememberMeParam(signInProperties.getRememberMeParam());
return filter;
}
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
shiroFilter.setLoginUrl(properties.getLoginUrl());
shiroFilter.setSuccessUrl(properties.getSuccessUrl());
shiroFilter.setUnauthorizedUrl(properties.getUnauthorizedUrl());
Map<String, Filter> filterMap = new LinkedHashMap<String, Filter>();
Class<? extends AuthorizationFilter> customAuthcFilterClass = properties.getCustomAuthcFilterClass();
if (null != customAuthcFilterClass ) {
AuthorizationFilter filter = BeanUtils.instantiate(customAuthcFilterClass);
filterMap.put("authc", filter);
} else {
filterMap.put("authc", formSignInFilter());
}
shiroFilter.setFilters(filterMap);
shiroFilter.setFilterChainDefinitionMap(properties.getFilterChainDefinitions());
return shiroFilter;
}
@Bean(name = "shiroFilter")
@DependsOn("securityManager")
@ConditionalOnMissingBean
public FilterRegistrationBean filterRegistrationBean(SecurityManager securityManager) throws Exception {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
//该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
filterRegistration.addInitParameter("targetFilterLifecycle", "true");
filterRegistration.setFilter((Filter) getShiroFilterFactoryBean(securityManager).getObject());
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
return filterRegistration;
}
}

View File

@@ -0,0 +1,73 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.realm.Realm;
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.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.annotation.Order;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
public class ShiroConfiguration {
@Bean(name = "lifecycleBeanPostProcessor")
@ConditionalOnMissingBean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@ConditionalOnMissingBean
@Bean(name = "defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
* (基于内存的)用户授权信息Cache
*/
@Bean(name = "shiroCacheManager")
@ConditionalOnMissingBean(name = "shiroCacheManager")
@ConditionalOnMissingClass(value = {"org.apache.shiro.cache.ehcache.EhCacheManager"})
public CacheManager shiroCacheManager() {
return new MemoryConstrainedCacheManager();
}
@Bean(name = "securityManager")
@DependsOn(value = {"shiroCacheManager", "rememberMeManager", "mainRealm"})
public DefaultSecurityManager securityManager(Realm realm, RememberMeManager rememberMeManager,
CacheManager cacheManager, SessionManager sessionManager) {
DefaultSecurityManager sm = new DefaultWebSecurityManager();
sm.setRealm(realm);
sm.setCacheManager(cacheManager);
sm.setSessionManager(sessionManager);
sm.setRememberMeManager(rememberMeManager);
return sm;
}
@Bean
@ConditionalOnMissingBean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
return aasa;
}
}

View File

@@ -0,0 +1,102 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
@ConfigurationProperties(prefix = "shiro.cookie")
public class ShiroCookieProperties {
private String name = "rememberMe";
private String value;
private int maxAge = 60 * 60 * 24 * 365; // one year
private int version = -1;
private boolean secure;
private boolean httpOnly = true;
private String cipherKey;
private String encryptionCipherKey;
private String decryptionCipherKey;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getMaxAge() {
return maxAge;
}
public void setMaxAge(int maxAge) {
this.maxAge = maxAge;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
public boolean isHttpOnly() {
return httpOnly;
}
public void setHttpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
}
public String getCipherKey() {
return cipherKey;
}
public void setCipherKey(String cipherKey) {
this.cipherKey = cipherKey;
}
public String getEncryptionCipherKey() {
return encryptionCipherKey;
}
public void setEncryptionCipherKey(String encryptionCipherKey) {
this.encryptionCipherKey = encryptionCipherKey;
}
public String getDecryptionCipherKey() {
return decryptionCipherKey;
}
public void setDecryptionCipherKey(String decryptionCipherKey) {
this.decryptionCipherKey = decryptionCipherKey;
}
}

View File

@@ -0,0 +1,74 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
@ConfigurationProperties(prefix = "shiro.realm.jdbc")
public class ShiroJdbcRealmProperties {
private boolean enabled;
private JdbcRealm.SaltStyle salt;
/**
* select password from users where username = ?
*/
private String authenticationQuery;
/**
* select role_name from user_roles where username = ?
*/
private String userRolesQuery;
/**
* select permission from roles_permissions where role_name = ?
*/
private String permissionsQuery;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getAuthenticationQuery() {
return authenticationQuery;
}
public void setAuthenticationQuery(String authenticationQuery) {
this.authenticationQuery = authenticationQuery;
}
public String getUserRolesQuery() {
return userRolesQuery;
}
public void setUserRolesQuery(String userRolesQuery) {
this.userRolesQuery = userRolesQuery;
}
public String getPermissionsQuery() {
return permissionsQuery;
}
public void setPermissionsQuery(String permissionsQuery) {
this.permissionsQuery = permissionsQuery;
}
public JdbcRealm.SaltStyle getSalt() {
return salt;
}
public void setSalt(JdbcRealm.SaltStyle salt) {
this.salt = salt;
}
}

View File

@@ -0,0 +1,153 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Map;
/**
* Configuration properties for Shiro.
*
* @author John Zhang
*/
@ConfigurationProperties(prefix = "shiro")
public class ShiroProperties {
/**
* Custom Realm
*/
private Class<? extends Realm> realmClass = null;
/**
* URL of login
*/
private String loginUrl = "/login";
/**
* URL of success
*/
private String successUrl = "/index";
/**
* URL of unauthorized
*/
private String unauthorizedUrl = "/unauthorized";
private String hashAlgorithmName = "MD5";
private int hashIterations = 1;
/**
* 密码重试次数上限
*/
private int retryMax = 100;
private boolean storedCredentialsHexEncoded = true;
/**
* Filter chain
*/
private Map<String, String> filterChainDefinitions;
private final Ehcache ehcache = new Ehcache();
/**
* Custom Realm
*/
private Class<? extends AuthorizationFilter> customAuthcFilterClass = null;
public Class<? extends Realm> getRealmClass() {
return realmClass;
}
public void setRealmClass(Class<? extends Realm> realmClass) {
this.realmClass = realmClass;
}
public String getLoginUrl() {
return loginUrl;
}
public void setLoginUrl(String loginUrl) {
this.loginUrl = loginUrl;
}
public String getSuccessUrl() {
return successUrl;
}
public void setSuccessUrl(String successUrl) {
this.successUrl = successUrl;
}
public String getUnauthorizedUrl() {
return unauthorizedUrl;
}
public void setUnauthorizedUrl(String unauthorizedUrl) {
this.unauthorizedUrl = unauthorizedUrl;
}
public String getHashAlgorithmName() {
return hashAlgorithmName;
}
public void setHashAlgorithmName(String hashAlgorithmName) {
this.hashAlgorithmName = hashAlgorithmName;
}
public int getHashIterations() {
return hashIterations;
}
public void setHashIterations(int hashIterations) {
this.hashIterations = hashIterations;
}
public int getRetryMax() {
return retryMax;
}
public void setRetryMax(int retryMax) {
this.retryMax = retryMax;
}
public boolean isStoredCredentialsHexEncoded() {
return storedCredentialsHexEncoded;
}
public void setStoredCredentialsHexEncoded(boolean storedCredentialsHexEncoded) {
this.storedCredentialsHexEncoded = storedCredentialsHexEncoded;
}
public Map<String, String> getFilterChainDefinitions() {
return filterChainDefinitions;
}
public void setFilterChainDefinitions(Map<String, String> filterChainDefinitions) {
this.filterChainDefinitions = filterChainDefinitions;
}
public Ehcache getEhcache() {
return ehcache;
}
public Class<? extends AuthorizationFilter> getCustomAuthcFilterClass() {
return customAuthcFilterClass;
}
public void setCustomAuthcFilterClass(Class<? extends AuthorizationFilter> customAuthcFilterClass) {
this.customAuthcFilterClass = customAuthcFilterClass;
}
public static class Ehcache {
private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";
public String getCacheManagerConfigFile() {
return cacheManagerConfigFile;
}
public void setCacheManagerConfigFile(String cacheManagerConfigFile) {
this.cacheManagerConfigFile = cacheManagerConfigFile;
}
}
}

View File

@@ -0,0 +1,74 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
@ConfigurationProperties(prefix = "shiro.session")
public class ShiroSessionProperties {
private long globalSessionTimeout = 30 * 60 * 1000L;
private boolean deleteInvalidSessions = true;
private long validationInterval = 60 * 60 * 1000L;
private boolean validationSchedulerEnabled = true;
private String activeSessionsCacheName = "shiro-activeSessionCache";
private Class<? extends SessionIdGenerator> idGenerator = JavaUuidSessionIdGenerator.class;
public long getGlobalSessionTimeout() {
return globalSessionTimeout;
}
public void setGlobalSessionTimeout(long globalSessionTimeout) {
this.globalSessionTimeout = globalSessionTimeout;
}
public boolean isDeleteInvalidSessions() {
return deleteInvalidSessions;
}
public void setDeleteInvalidSessions(boolean deleteInvalidSessions) {
this.deleteInvalidSessions = deleteInvalidSessions;
}
public long getValidationInterval() {
return validationInterval;
}
public void setValidationInterval(long validationInterval) {
this.validationInterval = validationInterval;
}
public boolean isValidationSchedulerEnabled() {
return validationSchedulerEnabled;
}
public void setValidationSchedulerEnabled(boolean validationSchedulerEnabled) {
this.validationSchedulerEnabled = validationSchedulerEnabled;
}
public String getActiveSessionsCacheName() {
return activeSessionsCacheName;
}
public void setActiveSessionsCacheName(String activeSessionsCacheName) {
this.activeSessionsCacheName = activeSessionsCacheName;
}
public Class<? extends SessionIdGenerator> getIdGenerator() {
return idGenerator;
}
public void setIdGenerator(Class<? extends SessionIdGenerator> idGenerator) {
this.idGenerator = idGenerator;
}
}

View File

@@ -0,0 +1,47 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for Shiro FormAuthenticationFilter
*
* @author John Zhang
*/
@ConfigurationProperties(prefix = "shiro.sign-in")
public class ShiroSignInProperties {
/**
* Request parameter's name of user
*/
private String userParam = "username";
/**
* Request parameter's name of password
*/
private String passwordParam = "password";
private String rememberMeParam = "rememberMe";
public String getUserParam() {
return userParam;
}
public void setUserParam(String userParam) {
this.userParam = userParam;
}
public String getPasswordParam() {
return passwordParam;
}
public void setPasswordParam(String passwordParam) {
this.passwordParam = passwordParam;
}
public String getRememberMeParam() {
return rememberMeParam;
}
public void setRememberMeParam(String rememberMeParam) {
this.rememberMeParam = rememberMeParam;
}
}

View File

@@ -0,0 +1,24 @@
package com.xinwei.spring.boot.autoconfigure.shiro;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.xinwei.spring.boot.autoconfigure.shiro.annotation.SessionUserArgumentResolver;
import java.util.List;
/**
* This guy is lazy, nothing left.
*
* @author John Zhang
*/
@Configuration
public class ShiroWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new SessionUserArgumentResolver());
}
}

View File

@@ -0,0 +1,39 @@
package com.xinwei.spring.boot.autoconfigure.shiro.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import com.xinwei.spring.boot.autoconfigure.shiro.ShiroWebMvcConfigurerAdapter;
/**
* Annotation to automatically register the following beans for usage with Spring MVC.
* <ul>
* <li>
* {@link com.xinwei.spring.boot.autoconfigure.shiro.annotation.SessionUser}.
* </li>
* </ul>
* @author John Zhang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Inherited
@Import({ EnableShiroWebSupport.ShiroWebMvcConfigurerAdapterImportSelector.class })
public @interface EnableShiroWebSupport {
static class ShiroWebMvcConfigurerAdapterImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] { ShiroWebMvcConfigurerAdapter.class.getName() };
}
}
}

View File

@@ -0,0 +1,14 @@
package com.xinwei.spring.boot.autoconfigure.shiro.annotation;
import java.lang.annotation.*;
/**
* 获取Shiro当前用户
* @author 张劲航
* @see SessionUserArgumentResolver
*/
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SessionUser {
}

View File

@@ -0,0 +1,30 @@
package com.xinwei.spring.boot.autoconfigure.shiro.annotation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
/**
* {@link SessionUser}注解的解析
* @author 张劲航
*/
public class SessionUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(SessionUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Subject subject = SecurityUtils.getSubject();
if(supportsParameter(parameter) && subject.isAuthenticated()){
return subject.getPrincipal();
}
return null;
}
}