写一个不花里胡哨的纯粹的Springboot+Shiro的入门小栗子

效果如图:

首页:有登录注册

先注册一个,然后登陆

登录,成功自动跳转到home页

home页:通过认证之后才可以进


代码部分:

依赖:

<?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>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>demo</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.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-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.5</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</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>

Java配置类:

package com.example.demo.conf;

import com.example.demo.auth.PermissionRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn; import java.util.LinkedHashMap; /**
* @program: boot-shiro
* @description:
* @author: 001977
* @create: 2018-07-17 18:22
*/
@Configuration
public class ShiroConfig { /**
* 1. 配置SecurityManager
* @return
*/
@Bean
public DefaultWebSecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm());
return securityManager;
} /**
* 2. 配置缓存
* @return
*/
@Bean
public CacheManager cacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
return ehCacheManager;
} /**
* 3. 配置Realm
* @return
*/
@Bean
public AuthorizingRealm realm(){
PermissionRealm realm = new PermissionRealm();
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
// 指定加密算法
matcher.setHashAlgorithmName("MD5");
// 指定加密次数
matcher.setHashIterations(10);
// 指定这个就不会报错
matcher.setStoredCredentialsHexEncoded(true);
realm.setCredentialsMatcher(matcher);
return realm;
} /**
* 4. 配置LifecycleBeanPostProcessor,可以来自动的调用配置在Spring IOC容器中 Shiro Bean 的生命周期方法
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
} /**
* 5. 启用IOC容器中使用Shiro的注解,但是必须配置第四步才可以使用
* @return
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
return new DefaultAdvisorAutoProxyCreator();
} /**
* 6. 配置ShiroFilter
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
LinkedHashMap<String, String> map = new LinkedHashMap<>();
// 静态资源
map.put("/css/**", "anon");
map.put("/js/**", "anon"); // 公共路径
map.put("/login", "anon");
map.put("/register", "anon");
//map.put("/*", "anon"); // 登出,项目中没有/logout路径,因为shiro是过滤器,而SpringMVC是Servlet,Shiro会先执行
map.put("/logout", "logout"); // 授权
map.put("/user/**", "authc,roles[user]");
map.put("/admin/**", "authc,roles[admin]"); // everything else requires authentication:
map.put("/**", "authc"); ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
// 配置SecurityManager
factoryBean.setSecurityManager(securityManager());
// 配置权限路径
factoryBean.setFilterChainDefinitionMap(map);
// 配置登录url
factoryBean.setLoginUrl("/");
// 配置无权限路径
factoryBean.setUnauthorizedUrl("/unauthorized");
return factoryBean;
} }

Realm类:

package com.example.demo.auth;

import com.example.demo.common.entity.User;
import com.example.demo.service.UserService;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet;
import java.util.Set; /**
* @program: boot-shiro
* @description:
* @author: 001977
* @create: 2018-07-12 13:03
*/
public class PermissionRealm extends AuthorizingRealm { @Autowired
private UserService userService; @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Object principal = principalCollection.getPrimaryPrincipal();
User user = (User) principal;
Set<String> roles = new HashSet<>();
roles.add("user");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
return info;
} @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken uToken = (UsernamePasswordToken) authenticationToken; String username = uToken.getUsername();
String password = String.valueOf(uToken.getPassword()); User user = userService.login(new User(username,password)); if(user == null){
throw new AuthenticationException("用户名密码不存在");
}
//认证的实体信息
Object principal = user;
//从数据库获取的密码
Object hashedCredentials = user.getPassword();
//盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername());
//当前Realm对象的name,调用父类的getName方法
String realmName = getName(); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, realmName); return info;
}
}

Controller:

package com.example.demo.controller;

import com.example.demo.common.TempStorage;
import com.example.demo.common.entity.User;
import com.example.demo.common.response.BaseResponse;
import com.example.demo.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; /**
* @program: boot-shiro
* @description:
* @author: 001977
* @create: 2018-07-12 13:02
*/
@RestController
public class SimpleController { @Autowired
private UserService userService; @RequestMapping("/")
public ModelAndView index(){
return new ModelAndView("index");
} @RequestMapping("/login")
public BaseResponse<String> login(@RequestBody User user){
BaseResponse<String> response = new BaseResponse<>(0,"登陆成功");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(
user.getUsername(), user.getPassword());
subject.login(token);
response.setData("/home");
return response;
} @RequestMapping("/register")
public BaseResponse register(@RequestBody User user){
userService.addUser(user);
return new BaseResponse(0,"注册成功");
} @RequestMapping("/home")
public ModelAndView home(){
ModelAndView mv = new ModelAndView("home");
mv.addObject("users", TempStorage.getInstance().getMap());
return mv;
}
}

其余代码参见GitHub

SpringBoot+Shiro入门小栗子的更多相关文章

  1. SpringBoot+Shiro+Redis共享Session入门小栗子

    在单机版的Springboot+Shiro的基础上,这次实现共享Session. 这里没有自己写RedisManager.SessionDAO.用的 crazycake 写的开源插件 pom.xml ...

  2. Java IO 与 NIO 服务器&客户端通信小栗子

    本篇包含了入门小栗子以及一些问题的思考 BIO package com.demo.bio; import java.io.*; import java.net.ServerSocket; import ...

  3. SpringBoot介绍,快速入门小例子,目录结构,不同的启动方式,SpringBoot常用注解

    SpringBoot介绍 引言 为了使用ssm框架去开发,准备ssm框架的模板配置 为了Spring整合第三方框架,单独的去编写xml文件 导致ssm项目后期xml文件特别多,维护xml文件的成本也是 ...

  4. springboot+shiro

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

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

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

  6. Shiro入门指引

    最近项目中用到Shiro,专门对其研究了一番,颇有收获,以下是笔者最近写的博客,希望对大家入门有所帮助. Shiro入门资源整理 Shiro在SpringBoot中的使用 Shiro源码解析-登录篇 ...

  7. 前端基于vue,后台采用springboot+shiro的方式搭建的一个移动端商品展示平台

    基于vue实现的移动端商品展示页,可以web-view的方式嵌入到小程序中,布局简约.大气,减少初学者或开发者不必要的工作量.后台维护采用的springboot+shiro的方式,为广大爱好者提供展示 ...

  8. SpringBoot+Shiro学习(七):Filter过滤器管理

    SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注  0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...

  9. SpringBoot&Shiro实现权限管理

    SpringBoot&Shiro实现权限管理 引言 相信大家前来看这篇文章的时候,是有SpringBoot和Shiro基础的,所以本文只介绍整合的步骤,如果哪里写的不好,恳请大家能指出错误,谢 ...

随机推荐

  1. 关于对ProgressBar定义模板的一些总结

    在之前的博客中曾经写到了一篇关于如何定义圆形进度条的文章,今天就ProgressBar再来进行一些总结,首先来介绍一下ProgressBar的结构,ProgressBar控件的模板有两个部分,我们在定 ...

  2. mysql 清除大数据表单

    背景:mysql数据库中有个日志表记录高达800多万,影响了mysql的正常业务访问,现需要清理三个月之前的所有数据,大概600多万(大概13G) 方法一:传统delete from xxx,传统,普 ...

  3. Python OpenCV人脸识别案例

    ■环境 Python 3.6.0 Pycharm 2017.1.3 ■库.库的版本 OpenCV 3.4.1 (cp36) ■haarcascades下载 https://github.com/ope ...

  4. Flask从入门到精通

    1. flask的下载和安装 在windows下安装flask flask依赖于两个库, 即werkzeug 和jinja2 , werkzeug负责服务器的部署, jinja2负责模板引擎,管理安装 ...

  5. 解决mybatis generator警告Cannot obtain primary key information from the database, generated objects may be incomplete

    使用 mybatis generator 生成pojo.dao.mapper时 经常出现 Cannot obtain primary key information from the database ...

  6. vue 響應接口

    全局方式: 增加屬性和set()和get(): vue.set(targname,key,vaule) targname:對象名或者數組名 key:字符串 value:任何值 刪除屬性和set()和g ...

  7. css伪元素之before和after

    css里面的伪元素主要是用来给选择器设置特殊效果.根据常用性,记录before和after. “:before”伪元素用来在元素的内容前面添加新的元素.比如标题前面会有一个小方块,就可以通过‘ :be ...

  8. 如何在虚拟机下配置centOS7

    链接地址:https://baijiahao.baidu.com/s?id=1597320700700593557&wfr=spider&for=pc

  9. Nginx 反向代理如何连接上游服务器

    L:92 想上游服务器先建立TCP连接 如三次握手 下面指令可以控制握手时间 proxy_next_upstream  指令当出现502可以换个上游服务器 Tcp keepalive 一般都是由进程在 ...

  10. 第二十一天,pickle json xml shelve configparser模块

    今日内容 1.pcikle 专用于python语言的序列化 2.json 是一种跨平台的数据格式 也属于序列化的一种方式 3.xml 可拓展标记语言 一种编写文档的语法 也支持跨平台 比较json而言 ...