SpringBoot整合Shiro实现登录认证的方法

 更新时间:2018年02月22日 16:22:39   作者:stackfing  
这篇文章主要介绍了SpringBoot整合Shiro实现登录认证的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

安全无处不在,趁着放假读了一下 Shiro 文档,并记录一下 Shiro 整合 Spring Boot 在数据库中根据角色控制访问权限

简介

Apache Shiro是一个功能强大、灵活的,开源的安全框架。它可以干净利落地处理身份验证、授权、企业会话管理和加密。

上图是 Shiro 的基本架构

Authentication(认证)

有时被称为“登录”,用来证明用户是用户他们自己本人

Authorization(授权)

访问控制的过程,即确定“谁”访问“什么”

Session Management(会话管理)

管理用户特定的会话,在 Shiro 里面可以发现所有的用户的会话信息都会由 Shiro 来进行控制

Cryptography(加密)

在对数据源使用加密算法加密的同时,保证易于使用

Start

环境

Spring Boot 1.5.9 MySQL 5.7 Maven 3.5.2 Spring Data Jpa Lombok

添加依赖

这里只给出主要的 Shiro 依赖

 <dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring-boot-starter</artifactId>
   <version>1.4.0-RC2</version>
  </dependency>

配置

我们暂时只需要用户表、角色表,在 Spring boot 中修改配置文件将自动为我们创建数据库表

server:
 port: 8888
spring:
 datasource:
 driver-class-name: com.mysql.jdbc.Driver
 username: root
 password: root
 url: jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8&useSSL=false
 jpa:
 generate-ddl: true
 hibernate:
  ddl-auto: update
 show-sql: true

实体

Role.java

@Data
@Entity
public class Role {

 @Id
 @GeneratedValue
 private Integer id;

 private Long userId;

 private String role;

}

User.java

@Data
@Entity
public class User {
 @Id
 @GeneratedValue
 private Long id;

 private String username;

 private String password;

}

Realm

首先建立 Realm 类,继承自 AuthorizingRealm,自定义我们自己的授权和认证的方法。Realm 是可以访问特定于应用程序的安全性数据(如用户,角色和权限)的组件。

Realm.java

public class Realm extends AuthorizingRealm {

 @Autowired
 private UserService userService;
 
 //授权
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 //从凭证中获得用户名
 String username = (String) SecurityUtils.getSubject().getPrincipal();
 //根据用户名查询用户对象
 User user = userService.getUserByUserName(username);
 //查询用户拥有的角色
 List<Role> list = roleService.findByUserId(user.getId());
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
 for (Role role : list) {
 //赋予用户角色
 info.addStringPermission(role.getRole());
 }
 return info;
 }

 //认证
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

 //获得当前用户的用户名
 String username = (String) authenticationToken.getPrincipal();

 //从数据库中根据用户名查找用户
 User user = userService.getUserByUserName(username);
 if (userService.getUserByUserName(username) == null) {
 throw new UnknownAccountException(
  "没有在本系统中找到对应的用户信息。");
 }

 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(),getName());
 return info;
 }

}

Shiro 配置类

ShiroConfig.java

@Configuration
public class ShiroConfig {
 @Bean
 public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
 shiroFilterFactoryBean.setSecurityManager(securityManager);
 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
 //以下是过滤链,按顺序过滤,所以/**需要放最后
 //开放的静态资源
 filterChainDefinitionMap.put("/favicon.ico", "anon");//网站图标
 filterChainDefinitionMap.put("/**", "authc");
 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 return shiroFilterFactoryBean;
 }

@Bean
 public DefaultWebSecurityManager securityManager() {
 DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm());
 return defaultWebSecurityManager;
 }

 @Bean
 public MyRealm myRealm() {
 MyRealm myRealm = new MyRealm();
 return myRealm;
 }
}

控制器

UserController.java

@Controller
public class UserController {

 @Autowired
 private UserService userService;

 @GetMapping("/")
 public String index() {
 return "index";
 }

 @GetMapping("/login")
 public String toLogin() {
 return "login";
 }

 @GetMapping("/admin")
 public String admin() {
 return "admin";
 }

 @PostMapping("/login")
 public String doLogin(String username, String password) {
 UsernamePasswordToken token = new UsernamePasswordToken(username, password);
 Subject subject = SecurityUtils.getSubject();
 try {
 subject.login(token);
 } catch (Exception e) {
 e.printStackTrace();
 }
 return "redirect:admin";
 }

 @GetMapping("/home")
 public String home() {
 Subject subject = SecurityUtils.getSubject();
 try {
 subject.checkPermission("admin");
 } catch (UnauthorizedException exception) {
 System.out.println("没有足够的权限");
 }
 return "home";
 }

 @GetMapping("/logout")
 public String logout() {
 return "index";
 }
}

Service

UserService.java

@Service
public class UserService {

 @Autowired
 private UserDao userDao;

 public User getUserByUserName(String username) {
 return userDao.findByUsername(username);
 }

 @RequiresRoles("admin")
 public void send() {
 System.out.println("我现在拥有角色admin,可以执行本条语句");
 }
}

展示层

admin.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en"/>
<head>
 <meta charset="UTF-8"/>
 <title>Title</title>
</head>
<body>

<form action="/login" method="post">
 <input type="text" name="username" />
 <input type="password" name="password" />
 <input type="submit" value="登录" />
</form>
</body>
</html>

home.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en"/>
<head>
 <meta charset="UTF-8"/>
 <title>Title</title>
</head>
<body>
home
</body>
</html>

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en"/>
<head>
 <meta charset="UTF-8"/>
 <title>Title</title>
</head>
<body>
index
<a href="/login" rel="external nofollow" >请登录</a>
</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en"/>
<head>
 <meta charset="UTF-8"/>
 <title>Title</title>
</head>
<body>

<form action="/login" method="post">
 <input type="text" name="username" />
 <input type="password" name="password" />
 <input type="submit" value="登录" />
</form>

</body>
</html>

总结

这个小案例实现了根据角色来控制用户访问,其中最重要的就是 Realm,它充当了Shiro与应用安全数据间的“桥梁”或者“连接器”

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • java解析JSON数据详解

    java解析JSON数据详解

    这篇文章主要介绍了java解析JSON数据详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等

    Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等

    这篇文章主要介绍了Java如何实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序,需要的朋友可以参考下
    2015-07-07
  • springboot整合mybatis流程详解

    springboot整合mybatis流程详解

    这篇文章主要为大家详细介绍了springboot整合mybatisplus的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-05-05
  • java实现俄罗斯方块游戏

    java实现俄罗斯方块游戏

    这篇文章主要为大家详细介绍了java实现俄罗斯方块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • 浅谈JavaWeb中的web.xml配置部署描述符文件

    浅谈JavaWeb中的web.xml配置部署描述符文件

    下面小编就为大家带来一篇浅谈JavaWeb中的web.xml配置部署描述符文件。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Spring 依赖注入实现示例

    Spring 依赖注入实现示例

    这篇文章主要介绍了Spring 依赖注入实现示例的相关资料,帮助大家更好的理解和使用spring框架,感兴趣的朋友可以了解下
    2020-11-11
  • Java基础知识精通块作用域与条件及switch语句

    Java基础知识精通块作用域与条件及switch语句

    块(block,即复合语句)是指由若干条 Java 语句组成的语句,并由一对大括号括起来。块确定了变量的作用域。一个块可以嵌套在另一个块中;条件语句、switch语句是我们常见会用到的结构,感兴趣的朋友来看看吧
    2022-04-04
  • SpringBoot2底层注解@Configuration配置类详解

    SpringBoot2底层注解@Configuration配置类详解

    这篇文章主要为大家介绍了SpringBoot2底层注解@Configuration配置类详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 详解java中if语句和switch的使用

    详解java中if语句和switch的使用

    这篇文章主要介绍了java中if语句和switch的使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • 基于maven实现私服搭建步骤图解

    基于maven实现私服搭建步骤图解

    这篇文章主要介绍了基于maven实现私服搭建步骤图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论