说明
上一章我们搭建好了springboot的基础框架,并引入了基础的orm框架和数据库等,今天主要集成shiro做登录权限的校验,废话不多说,开始构建程序代码。
引入
首先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");
//错误页面,认证不通过跳转
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实现缓存
*
* @return
*/
@Bean
public RedisCacheManager cacheManager(RedisProperties commonProperties) {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager(commonProperties));
return redisCacheManager;
}
/**
* 使用Redis实现 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 {
//否则默认从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 重写权限过滤
*
* @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;
}
}
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法(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;
}
/**
* 获取权限,string存放的是权限编码
*
* @param user
* @return
*/
private List<String> getPermCodes(User user) {
//TODO 你的权限编码处理
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 {
/**
* 获取当前用户
*
* @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;
}
}
结束
主要的部分是在shiroFilter进行过滤
MyShiroRealm做权限编码校验
说明
- 本文只做学习参考,如有任何不准确的地方欢迎指正。
- 源码参考 :https://gitee.com/lulongji/springboot-demo.git
- 我的邮箱:
lulongji2011@163.com
版权声明:
本文为博主原创文章,转载请附上原文出处链接和本声明。