說明
上一章我們搭建好了springboot的基礎(chǔ)框架,并引入了基礎(chǔ)的orm框架和數(shù)據(jù)庫等,今天主要集成shiro做登錄權(quán)限的校驗,廢話不多說,開始構(gòu)建程序代碼。
引入
首先pom文件要引入shiro的jar包,如下:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
引入模板引擎freemarker:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>net.mingsoft</groupId>
<artifactId>shiro-freemarker-tags</artifactId>
<version>0.1</version>
</dependency>
配置ShiroConfig
package com.example.demo.config;
import com.example.demo.core.shiro.MyShiroRealm;
import com.example.demo.domain.properties.RedisProperties;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
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.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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 java.util.LinkedHashMap;
import java.util.Map;
/**
* @author lu
*/
@ConditionalOnWebApplication
@Configuration
@EnableConfigurationProperties({RedisProperties.class})
public class ShiroConfig {
@Bean
public FilterRegistrationBean delegatingFilterProxy() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
DelegatingFilterProxy proxy = new DelegatingFilterProxy();
proxy.setTargetFilterLifecycle(true);
proxy.setTargetBeanName("shiroFilter");
filterRegistrationBean.setFilter(proxy);
return filterRegistrationBean;
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login/loginPage");
shiroFilterFactoryBean.setSuccessUrl("/login/main");
shiroFilterFactoryBean.setUnauthorizedUrl("/login/500");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login/**", "anon");
filterChainDefinitionMap.put("/res/** ", "anon");
filterChainDefinitionMap.put("/**", "authc");
//錯誤頁面,認(rèn)證不通過跳轉(zhuǎn)
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
// @Bean
// public Realm shiroRealm(HashedCredentialsMatcher matcher) {
// MyShiroRealm myShiroRealm = new MyShiroRealm();
// myShiroRealm.setCredentialsMatcher(matcher);
// return myShiroRealm;
// }
@Bean
public Realm shiroRealm() {
return new MyShiroRealm();
}
@Bean
public SecurityManager securityManager(RedisProperties commonProperties) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRememberMeManager(rememberMeManager());
securityManager.setSessionManager(sessionManager(commonProperties));
securityManager.setCacheManager(cacheManager(commonProperties));
securityManager.setRealm(shiroRealm());
return securityManager;
}
// @Bean
// public SecurityManager securityManager(RedisProperties commonProperties) {
// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// securityManager.setRememberMeManager(rememberMeManager());
// securityManager.setSessionManager(sessionManager(commonProperties));
// securityManager.setCacheManager(cacheManager(commonProperties));
// securityManager.setRealm(shiroRealm(hashedCredentialsMatcher()));
// return securityManager;
// }
@Bean
public SimpleCookie rememberCookie() {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
return simpleCookie;
}
@Bean
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberCookie());
cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(0);
return credentialsMatcher;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 開啟Shiro的注解支持
* 比如:@RequireRoles @RequireUsers
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public SessionManager sessionManager(RedisProperties commonProperties) {
MySessionManager mySessionManager = new MySessionManager();
mySessionManager.setSessionDAO(redisSessionDAO(commonProperties));
// mySessionManager.setCacheManager(cacheManager());
mySessionManager.setSessionIdUrlRewritingEnabled(true);
return mySessionManager;
}
@Bean
public RedisManager redisManager(RedisProperties commonProperties) {
RedisManager redisManager = new RedisManager();
redisManager.setHost(commonProperties.getHost());
redisManager.setPort(commonProperties.getPort());
redisManager.setTimeout(commonProperties.getTimeout());
redisManager.setPassword(commonProperties.getPassword());
return redisManager;
}
/**
* redis實現(xiàn)緩存
*
* @return
*/
@Bean
public RedisCacheManager cacheManager(RedisProperties commonProperties) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager(commonProperties));
return redisCacheManager;
}
/**
* 使用Redis實現(xiàn) shiro sessionDao
*
* @return
*/
@Bean
public RedisSessionDAO redisSessionDAO(RedisProperties commonProperties) {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager(commonProperties));
return redisSessionDAO;
}
}
MySessionManager管理
package com.example.demo.config;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
public class MySessionManager extends DefaultWebSessionManager {
private static final String AUTHORIZATION = "X-Token";
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
public MySessionManager() {
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//獲取請求頭中X-Token中保存的sessionId
String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
if (!StringUtils.isEmpty(id)) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
} else {
//否則默認(rèn)從cookie中獲取sessionId
return super.getSessionId(request, response);
}
}
}
reids緩存
package com.example.demo.domain.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedisProperties {
private String host;
private int port;
private String password;
private int timeout;
private int database;
}
你的ShiroRealm 處理
package com.example.demo.core.shiro;
import com.example.demo.domain.User;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* shiroRealm 重寫權(quán)限過濾
*
* @author lu
*/
@Component
public class MyShiroRealm extends AuthorizingRealm {
/**
* 登錄信息和用戶驗證信息驗證(non-Javadoc)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal(); // 得到用戶名
String password = new String((char[]) token.getCredentials()); // 得到密碼
if (null != username && null != password) {
return new SimpleAuthenticationInfo(username, password, getName());
} else {
return null;
}
}
/**
* 授權(quán)查詢回調(diào)函數(shù), 進行鑒權(quán)但緩存中無用戶的授權(quán)信息時調(diào)用,負(fù)責(zé)在應(yīng)用程序中決定用戶的訪問控制的方法(non-Javadoc)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
User user = null;
try {
user = AuthUtil.getCurrentUser();
} catch (Exception e) {
e.printStackTrace();
}
SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
simpleAuthorInfo.addStringPermissions(getPermCodes(user));
return simpleAuthorInfo;
}
/**
* 獲取權(quán)限,string存放的是權(quán)限編碼
*
* @param user
* @return
*/
private List<String> getPermCodes(User user) {
//TODO 你的權(quán)限編碼處理
return null;
}
}
用戶session
package com.example.demo.core.shiro;
import com.example.demo.domain.User;
import com.lulj.base.json.FastjsonUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
/**
* 用戶公共類
*
* @author lu
*
*/
public class AuthUtil {
/**
* 獲取當(dāng)前用戶
*
* @return
*/
public static User getCurrentUser() throws Exception {
User user;
Subject sub = SecurityUtils.getSubject();
Session session = sub.getSession();
Object userJson = session.getAttribute("session_user");
if (userJson != null) {
user = FastjsonUtils.jsonToBean(User.class, userJson.toString());
} else {
return null;
}
return user;
}
}
結(jié)束
主要的部分是在shiroFilter進行過濾
image.png
MyShiroRealm做權(quán)限編碼校驗
image.png
說明
- 本文只做學(xué)習(xí)參考,如有任何不準(zhǔn)確的地方歡迎指正。
- 源碼參考 :https://gitee.com/lulongji/springboot-demo.git
- 我的郵箱:
lulongji2011@163.com
版權(quán)聲明:
本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

