进阶教程:

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

  返回:退出登录成功

springboot+shiro整合教程的更多相关文章

  1. Springboot + shiro 整合之Url拦截设置(转)

    shiro 整合到springboot 还是比较简单的,只需要新建一个spring-shiro.xml的配置文件: <span style="font-size:14px;" ...

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

    相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群re ...

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

    相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3.springboot+shiro+redis(单机red ...

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

    相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(集群redis版)整合教程 3.springboot+shiro+redis(单机red ...

  5. springboot+shiro

    作者:纯洁的微笑 出处:http://www.ityouknow.com/ 这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公 ...

  6. Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...

  7. (八) SpringBoot起飞之路-整合Shiro详细教程(MyBatis、Thymeleaf)

    兴趣的朋友可以去了解一下前几篇,你的赞就是对我最大的支持,感谢大家! (一) SpringBoot起飞之路-HelloWorld (二) SpringBoot起飞之路-入门原理分析 (三) Sprin ...

  8. springboot+shiro+redis项目整合

    介绍: Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最 ...

  9. springboot 与 shiro 整合 (简洁版)

    前言: 网上有很多springboot 与 shiro 整合的资料,有些确实写得很好, 对学习shiro和springboot 都有很大的帮助. 有些朋友比较省事, 直接转发或者复制粘贴.但是没有经过 ...

随机推荐

  1. Python写入连接mysql失败

    执行如下连接数据库的语句: engine = create_engine('mysql://root:root@127.0.0.1/stock?charset=utf8') 报错如下: ImportE ...

  2. django配置数据库

    配置数据库 Django默认使用SQLite数据库 在settings.py文件中通过DATABASES选项进行数据库配置 配置MySQL Python3.x中安装的是PyMySQL 在__init_ ...

  3. iOS开发:代码通用性以及其规范 第一篇(附带,自定义UITextView\进度条\双表显示\瀑布流 代码设计思路)

    在iOS团队开发中,我见过一些人的代码,也修改过他们的代码.有的人的代码写的非常之规范.通用,几乎不用交流,就可以知道如何修改以及在它基础上扩展延生.有的人的代码写的很垃圾,一眼看过去,简直会怀疑自己 ...

  4. Android开发(七)——判断网络状态

    项目中难免会出现使用网络的情况,使用网络前得进行网络判断,看网上的网友一般有多种实现版本. 第一种: // 是否有网络连接 public static boolean isNetworkConnect ...

  5. 移动web开发(一)——移动web开发必备知识

    参考: 移动终端开发必备知识.http://isux.tencent.com/mobile-development-essential-knowledge.html

  6. ios9 之后使用CFNumberGetValue出错

    将编译源类型设置为根据文件而定:

  7. 基于9款CSS3鼠标悬停相册预览特效

    基于9款CSS3鼠标悬停相册预览特效里面包含九款不同方式的相册展开特效代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="albums&q ...

  8. 纯CSS3打造非常炫的加载动画

    纯css3打造的一款非常炫的加载图.用在需要一定时间加载的地方非常合适.先上效果图: 点击这里在线预览 代码非常简单.没有用任何javascript代码.纯css3实现. html代码: <di ...

  9. Java基础篇--字符串处理(StringBuffer)

    字符串处理 在Java中最常将字符串作为String类型对象来处理.同时String中也提供了很多操作字符串的函数(可自行查阅资料),而本篇将介绍StringBuffer如何操作字符串. String ...

  10. C#使用System.IO.Path获取文件路径、文件名

    class Program { static void Main(string[] args) { //获取当前运行程序的目录 string fileDir = Environment.Current ...