您的位置:首页 > 数据库 > Redis

sprinboot+shiro+redis(用到crazycake)实现用户权限管理demo

2019-08-09 15:41 399 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/cty_com/article/details/98960799

sprinboot+shiro+redis实现用户权限管理demo

建立数据库

建立5张表,分别是用户表、角色表、权限表、用户角色表、角色权限表:

其中用户表、角色表、权限表是实体表,用户角色表、角色权限表是功能表,用于连接三张实体表。

注入依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>

创建实体model和dao层

这里用到maven自动工具,故不细说。
但是有一点需要提到的是,其中由于用户表需要实现持久化,所以用户类需要继承Serializable这个接口,至于为什么要用到接口Serializable,参考博客:为什么要实现Serializable

写redis配置

在application.yml中配置redis相关静态变量,如下:

shiro:
redis:
host: 127.0.0.1:6379
timeout: 1800000

这里只写了端口与连接超时时长。
接着写一个redis的配置类:

@Configuration
public class New_RedisConfig {

@Value("${shiro.redis.host}")
private String host;

@Value("${shiro.redis.timeout}")
private int timeout;

//    private String password;

public String getHost() {
return host;
}

public void setHost(String host) {
this.host = host;
}

public int getTimeout() {
return timeout;
}

public void setTimeout(int timeout) {
this.timeout = timeout;
}

}

自定义realm

public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;

@Autowired
private IAuthQueryService authQueryService;
/**
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
if (principalCollection == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
}
Object principal = getAvailablePrincipal(principalCollection);
if(!(principal instanceof User)) {
return null;
}

User curUser = (User) principal;
List<Role> roleList = authQueryService.queryRolesByUser(curUser.getId());
Set<String> roles = new HashSet<>();
roleList.forEach(role -> roles.add(role.getName()));
List<Perm> permList = authQueryService.queryPermsByUser(curUser.getId());
Set<String> perms = new HashSet<>();
permList.forEach(perm -> perms.add(perm.getRemark()));
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(perms);
return info;
}

/**
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑");
UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
String username = upToken.getUsername();
String password=new String(upToken.getPassword());
if (StringUtils.isEmpty(username)) {
throw new AccountException("用户名不能为空");
}
if (StringUtils.isEmpty(password)) {
throw new AccountException("密码不能为空");
}
User user = new User();
user.setUsername(username);
user.setPassword(password);
List<User> list = userService.list(user);

if(list.size() == 0){
throw new UnknownAccountException("用户名未注册");
}
if(list.size()>1){
throw new UnknownAccountException("该用户名存在多个账号");
}
User user_in_database = list.get(0);
if (!user_in_database.getPassword().equals(user.getPassword())){
throw new InvalidAccountException("密码错误");
}
return new SimpleAuthenticationInfo(user_in_database, password, getName());//搞清楚几个参数含义
}
}

这个自定义的UserRealm 必须实现AuthorizingRealm 接口,并实现doGetAuthorizationInfo(授权方法)和 doGetAuthenticationInfo(认证方法),前者是权限的管理,后者是登陆认证的管理。
另外在上面代码中,我实现的是权限动态的获取,从perm表和role表里把用户的perm和role都查出来存入info中(至于这个info是不是存入缓存中了,我一时也想不起来,以后再说)。

配置shiro

@Configuration
public class ShiroConfig {
@Autowired
private IAuthQueryService authQueryService;

/**
* 1.Realm
*/
@Bean(name = "userRealm")
public UserRealm getUserRealm(){
return new UserRealm();
}

/**
* 2.DefaultWebSecurityManager
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(userRealm);
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* 3.ShiroFirterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
System.out.println("Shiro注入成功");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//安全管理器(关联SecurityManager)
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 获取匿名权限url
List<Perm> perms = authQueryService.queryAnonPerms();
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//开放匿名方法
if(perms != null && perms.size() > 0) {
perms.forEach(perm -> {
if(!StringUtils.isEmpty(perm.getPermUrl())) {
filterChainDefinitionMap.put(perm.getPermUrl(), "anon");
}});
}
//添加过滤器
filterChainDefinitionMap.put("/demo3/user/*","anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
filters.put("authc", shiroAccessFilter());
return shiroFilterFactoryBean;
}
//生命周期处理器
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public static DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
//未登录拦截
@Bean
public ShiroAccessFilter shiroAccessFilter() {
return new ShiroAccessFilter();
}

@Bean
public RedisCacheManager redisCacheManager(){
// crazycake 实现
RedisCacheManager cacheManager = new RedisCacheManager();
cacheManager.setRedisManager(redisManager());
return cacheManager;
}
@Bean
public RedisManager redisManager(){
// crazycake 实现
New_RedisConfig redisConfig = redisConfig();
RedisManager redisManager = new RedisManager();
redisManager.setHost(redisConfig.getHost());
redisManager.setTimeout(redisConfig.getTimeout());
return redisManager;
}

@Bean
public New_RedisConfig redisConfig(){
return new New_RedisConfig();
}

@Bean
public DefaultWebSecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(customizedModularRealmAuthenticator());
List<Realm> realms = new ArrayList<>();
realms.add(getUserRealm());
securityManager.setRealms(realms);
// 设置sessionManager
securityManager.setSessionManager(sessionManager());
securityManager.setCacheManager(redisCacheManager()); // 配置缓存的话,退出登录的时候crazycake会报错,要求放在session里面的实体类必须有个id标识
return securityManager;
}

@Bean
public CustomizedModularRealmAuthenticator customizedModularRealmAuthenticator() {
CustomizedModularRealmAuthenticator authenticator = new CustomizedModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
return authenticator;
}

@Bean
public FilterRegistrationBean registration(ShiroAccessFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}

@Bean
public SessionManager sessionManager(){
LoginWebSessionManager sessionManager = new LoginWebSessionManager();
// 设置session超时
sessionManager.setGlobalSessionTimeout(redisConfig().getTimeout());
// 删除无效session
sessionManager.setDeleteInvalidSessions(true);
// 设置JSESSIONID
sessionManager.setSessionIdCookie(cookie());
// 设置sessionDAO
sessionManager.setSessionDAO(sessionDAO());
return sessionManager;
}

@Bean
public SimpleCookie cookie(){
//  cookie的name,对应的默认是 JSESSIONID
SimpleCookie cookie = new SimpleCookie("SHAREJSESSIONID");
cookie.setHttpOnly(true);
//  path为 / 用于多个系统共享JSESSIONID
cookie.setPath("/");
return cookie;
}

@Bean
public RedisSessionDAO sessionDAO(){
// crazycake 实现
RedisSessionDAO sessionDAO = new RedisSessionDAO();
sessionDAO.setKeyPrefix("demo3:session:");
sessionDAO.setRedisManager(redisManager());
// Session ID 生成器
sessionDAO.setSessionIdGenerator(sessionIdGenerator());
return sessionDAO;
}

@Bean
public JavaUuidSessionIdGenerator sessionIdGenerator(){
return new JavaUuidSessionIdGenerator();
}

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}

还有很多工具类,不一一拿出来细说,我放在上传资源中。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐