进阶教程:

1. springboot+shiro+redis(单机redis版)整合教程

2. springboot+shiro+redis(集群redis版)整合教程

3.springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)

本教程整合环境: java8 maven

开发工具: idea

版本: springboot 1.5.15.RELEASE

注:

1.本教程数据操作是模拟数据库操作,并没有真正进行持久化,自行修改即可。

2.角色权限验证未实现,只实现基本的登录验证,自行扩展即可。

项目结构:

pom.xml:

<?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">
<modelVersion>4.0.0</modelVersion> <groupId>webapp</groupId>
<artifactId>springboot-shiro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>springboot-shiro</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.15.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

application.yml:

server:
port: 1000

User.java:

package webapp.model;

import lombok.Data;

/**
* Created by Administrator on 2018/9/5.
*/
@Data
public class User {
private Long id;
private String userName;
private String password;
}

UserService.java:

package webapp.service;

import webapp.model.User;

/**
* Created by Administrator on 2018/9/5.
*/
public interface UserService {
User findOneByUserName(String userName);
}

UserServiceImpl.java:

package webapp.service.impl;

import org.springframework.stereotype.Service;
import webapp.model.User;
import webapp.service.UserService; /**
* Created by Administrator on 2018/9/5.
*/
@Service
public class UserServiceImpl implements UserService { @Override
public User findOneByUserName(String userName) {
User user = new User();
user.setId(1L);
user.setUserName("007少侠");
user.setPassword("123456");
return user;
}
}

UserController.java:

package webapp.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import webapp.service.UserService; import java.io.Serializable; /**
* Created by Administrator on 2018/9/5.
*/
@RestController
@RequestMapping("/core/user")
public class UserController {
@Autowired
private UserService userService; /**
* 登录
* @param
* @return
*/
@GetMapping("/login")
public String login(String userName, String password) {
System.out.println("登录" + userName); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
subject.login(token); Session session = subject.getSession();
Serializable sessionId = session.getId();
System.out.println("登录成功 -> " + sessionId); return userName + "[" + sessionId + "]";
} @GetMapping("/logout")
public String logout() {
SecurityUtils.getSubject().logout();
return "退出登录成功";
} /**
* 获取当前登录用户
* @return
*/
@GetMapping("/findUser")
public String findUser() {
Subject subject = SecurityUtils.getSubject();
PrincipalCollection collection = subject.getPrincipals();
if (null != collection && !collection.isEmpty()) {
String userName = (String) collection.iterator().next();
System.out.println("获取当前登录用户" + userName);
return userService.findOneByUserName(userName).toString();
}
return "{\n" +
" \"codeEnum\": \"OVERTIME\",\n" +
" \"code\": 0,\n" +
" \"data\": null,\n" +
" \"msg\": \"未登陆/登陆超时\",\n" +
" \"success\": false\n" +
"}";
}
}

下面为shiro基本配置:

UserShiroRealm.java:

package webapp.shiro;

import org.apache.shiro.SecurityUtils;
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.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.springframework.beans.factory.annotation.Autowired;
import webapp.model.User;
import webapp.service.UserService; import java.util.Collection; /**
* Created by Administrator on 2018/9/5.
*/
public class UserShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private SessionDAO sessionDAO; /**
* 角色权限和对应权限添加
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
} /**
* 用户认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
} String userName = authenticationToken.getPrincipal().toString(); //只允许同一账户单个登录
Subject subject = SecurityUtils.getSubject();
Session nowSession = subject.getSession();
Collection<Session> sessions = sessionDAO.getActiveSessions();
if(sessions != null && sessions.size() > 0) {
for (Session session : sessions) {
if (!nowSession.getId().equals(session.getId()) && (session.getTimeout() == 0
|| userName.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY))))) {
sessionDAO.delete(session);
}
}
} User user = userService.findOneByUserName(userName);
if (user == null) {
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
return new SimpleAuthenticationInfo(userName, user.getPassword(), getName());
}
}
}

ShiroCoreController.java:

package webapp.shiro;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; /**
* Created by Administrator on 2018/9/5.
*/
@RestController
public class ShiroCoreController {
@GetMapping("/loginUnAuth")
public String loginUnAuth() {
return "{\n" +
" \"codeEnum\": \"OVERTIME\",\n" +
" \"code\": 0,\n" +
" \"data\": null,\n" +
" \"msg\": \"未登陆/登陆超时\",\n" +
" \"success\": false\n" +
"}";
}
@GetMapping("/authorUnAuth")
public String authorUnAuth() {
return "{\n" +
" \"codeEnum\": \"ERR_PERMISSIONS\",\n" +
" \"code\": -2,\n" +
" \"data\": null,\n" +
" \"msg\": \"无此权限\",\n" +
" \"success\": false\n" +
"}";
}
}

shiro配置类ShiroConfiguration.java:

package webapp.conf;

import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
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.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import webapp.shiro.UserShiroRealm; import java.util.HashMap; /**
* shiro配置类
* Created by Administrator on 2018/9/5.
*/
@Configuration
public class ShiroConfiguration { //将自己的验证方式加入容器
@Bean
public UserShiroRealm userShiroRealm() {
return new UserShiroRealm();
} @Bean
public MemorySessionDAO getMemorySessionDAO() {
return new MemorySessionDAO();
} @Bean
public SimpleCookie getSimpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName("SHRIOSESSIONID");
return simpleCookie;
} @Bean
public MemoryConstrainedCacheManager memoryConstrainedCacheManager() {
return new MemoryConstrainedCacheManager();
} //配置shiro session 的一个管理器
@Bean
public DefaultWebSessionManager getDefaultWebSessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(getMemorySessionDAO());
sessionManager.setGlobalSessionTimeout(-1000); //session有效期 默认值1800000 30分钟 1800000毫秒 -1000表示永久
SimpleCookie simpleCookie = getSimpleCookie();
simpleCookie.setHttpOnly(true); //设置js不可读取此Cookie
simpleCookie.setMaxAge(3 * 365 * 24 * 60 * 60); //3年 cookie有效期
sessionManager.setSessionIdCookie(simpleCookie);
return sessionManager;
} //配置核心安全事务管理器
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(userShiroRealm());
manager.setCacheManager(memoryConstrainedCacheManager());
manager.setSessionManager(getDefaultWebSessionManager());
return manager;
} //加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
} //Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
HashMap<String, String> map = new HashMap<>();
//登出
//map.put("/logout", "logout");
//认证 /###/@@@/**
map.put("/api/**", "authc"); //登录认证不通过跳转
shiroFilterFactoryBean.setLoginUrl("/loginUnAuth");
//首页
//shiroFilterFactoryBean.setSuccessUrl("/index");
//权限认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/authorUnAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
}

启动项目,访问相关接口校验是否成功:

登录接口:http://localhost:1000/core/user/login?userName=002&password=123456

  返回:002[42c6d423-e48e-4164-b17d-0cbc0f9ca832]

获取用户:http://localhost:1000/core/user/findUser

  返回:User(id=1, userName=007少侠, password=123456)

退出登录:http://localhost:1000/core/user/logout

  返回:退出登录成功

最新文章

  1. 【转】TensorFlow练习20: 使用深度学习破解字符验证码
  2. UI控件(UISlider)
  3. html5游戏-追踪算法
  4. Hadoop:Windows 7 32 Bit 编译与运行
  5. Android实例-实现扫描二维码并生成二维码(XE8+小米5)
  6. The 5th Zhejiang Provincial Collegiate Programming Contest------ProblemK:Kinds of Fuwas
  7. JAVASCRIPT——文字出现效果练习
  8. Apache JMeter开源压力测试/负载测试工具 2.12 官方最新版
  9. hadoop调度程序时出现“Error opening job jar”错误
  10. Windows API 函数浏览
  11. java面试题之int和Integer的区别
  12. 将html table 转成 excel
  13. 拖动DIV
  14. vue-cli脚手架目录一览
  15. [Python学习笔记-006] 使用stomp.py校验JMS selector的正确性
  16. kafka_2.10-0.8.1.1.tgz的1或3节点集群的下载、安装和配置(图文详细教程)绝对干货
  17. 【bzoj2806】 Ctsc2012—Cheat
  18. Centos安装Perforce
  19. iOS 事件传递及响应过程
  20. linux学习之用户的切换

热门文章

  1. MySQL字段数据全部查出【只保留中文、英文、数字、空格的词表】
  2. WebService 获取当前URL
  3. google3aac509c9040e79d
  4. Java SWT编程基础
  5. python keras 神经网络框架 的使用以及实例
  6. springboot 使用c3p0数据库连接池
  7. Postgresql分表与优化
  8. PHP——安装wampserver丢失MSVCR110.dll
  9. Java编程的逻辑 (29) - 剖析String
  10. .net 定时启动任务