【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

时间:2022-09-02 15:21:12

开发环境搭建参见《【原】无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页

需求:

① 除了登录页面,在地址栏直接访问其他URL,均跳转至登录页面

② 登录涉及帐号和密码,帐号错误提示帐号错误,密码错误提示密码错误

③ 登录成功跳转至首页,首页显示登录者帐号信息,并有注销帐号功能,点击注销退出系统

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

分析:

典型的运用认证权限的需求,考虑使用Shiro。了解一下Shiro框架,Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

关键词汇:

① Subject:安全术语,本意是“当前的操作用户”。

在安全领域,术语“Subject”可以是人,也可以是第三方进程、后台帐户(Daemon Account)、定时作业(Corn Job)或其他类似事物。

它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。

在程序中能轻易获得Subject,允许在任何需要的地方进行安全操作。

每个Subject对象都必须与一个SecurityManager进行绑定,访问Subject对象其实都是在与SecurityManager里的特定Subject进行交互。

② SecurityManager:安全管理器。

Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。

③ Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限),

即SecurityManager要验证用户身份,需要从Realm获取相应用户进行比较以确定用户身份是否合法;

也就是说需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,安全数据源。

④ authentication:认证(发音:[ɔ:ˌθentɪ'keɪʃn])

⑤ authorization:授权(发音:[ˌɔ:θərəˈzeɪʃn])

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0、数据库建表init.sql

 DROP TABLE sys_user;

 CREATE TABLE sys_user
(
userid INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
username VARCHAR(10) NOT NULL COMMENT '用户名称',
`password` VARCHAR(10) NOT NULL COMMENT '用户密码'
); INSERT INTO sys_user VALUES(NULL, 'admin', ''), (NULL, 'test', ''); SELECT * FROM sys_user;

1、编写项目对象模型文件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>cn.temptation</groupId>
<artifactId>studyShiro</artifactId>
<version>1.0-SNAPSHOT</version> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent> <dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mariadb -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.2.5</version>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- 热启动 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

2、编写项目配置文件application.properties

 # 数据库访问配置
# 对应MariaDB驱动
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
# 数据源配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=sa
# 配置Springboot默认支持的Hikari数据库连接池
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
# Spring Data JPA配置
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# 格式化输出的json字符串
spring.jackson.serialization.indent_output=true
# 设置控制台彩色打印
spring.output.ansi.enabled=ALWAYS

3、编写项目启动类Application.java

 package cn.temptation;

 import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class Application {
public static void main(String[] args) {
// SpringBoot项目启动
SpringApplication.run(Application.class, args);
}
}

4、编写登录页面login.html 和 首页页面index.html

登录页面:login.html

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>系统登录</title>
</head>
<body>
<div th:text="${msg}" style="color: red"></div>
<form action="doLogin" method="post">
帐号:<input type="text" id="txtUsername" name="username" /><br/>
密码:<input type="password" id="txtPassword" name="password" /><br/><br/>
<input type="submit" value="提交" />&nbsp;<input type="reset" value="重置" />
</form>
</body>
</html>

首页页面:index.html

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>系统首页</title>
</head>
<body>
<div th:text="${'欢迎您,' + currentuser}" style="color: red;float: left;"></div>
<div style="color: red;float: right;"><a href="doLogout">注销</a></div>
</body>
</html>

5、编写Shiro框架用配置类ShiroConfig.java 和 自定义Realm类MyRealm.java

配置类ShiroConfig.java

 package cn.temptation.shiro;

 import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap;
import java.util.Map; /**
* Shiro配置类
*/
@Configuration
public class ShiroConfig {
// 1、创建ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); // 设置登录跳转页面
shiroFilterFactoryBean.setLoginUrl("/login"); /**
* Shiro内置过滤器:实现权限相关的拦截
* 常用过滤器:
* anon(认证用):无需认证(登录)即可访问
* authc(认证用):必须认证才可访问
* user(少用):使用rememberMe功能可以访问
* perms(授权用):必须得到资源权限才可访问
* role(授权用):必须得到角色权限才可访问
*/
Map<String, String> filterMap = new LinkedHashMap<>(); // 放行登录请求
filterMap.put("/doLogin", "anon"); // 配置退出过滤器,退出代码Shiro已经实现
filterMap.put("/logout", "logout"); // 过滤链定义,从上向下顺序执行,一般将/*放在最下边
filterMap.put("/*", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean;
} // 2、创建DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); // 关联Realm
defaultWebSecurityManager.setRealm(myRealm); return defaultWebSecurityManager;
} // 3、创建Realm
@Bean(name = "myRealm")
public MyRealm getRealm() {
return new MyRealm();
}
}

自定义Realm类MyRealm.java

 package cn.temptation.shiro;

 import cn.temptation.dao.UserDao;
import cn.temptation.domain.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; /**
* 自定义Realm
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserDao userDao; // 授权处理
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
} // 认证处理
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 编写Shiro判断逻辑,判断账号和密码
// 1、判断账号
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; User user = userDao.findByUsername(token.getUsername());
if (user == null) {
// 账号错误,Shiro底层会抛出UnknownAccountException异常
return null;
} // 2、判断密码
return new SimpleAuthenticationInfo("", user.getPassword(), "");
}
}

6、编写实体类User.java

 package cn.temptation.domain;

 import javax.persistence.*;

 @Entity
@Table(name = "sys_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "userid")
private Integer userid; @Column(name = "username")
private String username; @Column(name = "password")
private String password; public Integer getUserid() {
return userid;
} public void setUserid(Integer userid) {
this.userid = userid;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
}
}

7、编写控制器类UserController.java

 package cn.temptation.web;

 import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; @Controller
public class UserController {
// 访问登录页
@RequestMapping("/login")
public String login() {
return "login";
} // 访问首页
@RequestMapping("/index")
public String index() {
return "index";
} // 登录处理
@RequestMapping("/doLogin")
public String doLogin(String username, String password, Model model) {
// 使用Shiro编写认证处理
// 1、获取Subject
Subject subject = SecurityUtils.getSubject(); // 2、封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password); // 3、执行登录
try {
// 登录成功
subject.login(token); // 返回当前用户的帐号
model.addAttribute("currentuser", token.getUsername()); return "index";
} catch (UnknownAccountException exception) {
// 返回错误信息
model.addAttribute("msg", "账号错误!"); return "login";
} catch (IncorrectCredentialsException exception) {
// 返回错误信息
model.addAttribute("msg", "密码错误!"); return "login";
}
} // 注销处理
@RequestMapping("/doLogout")
public String doLogout() {
// 1、获取Subject
Subject subject = SecurityUtils.getSubject(); // 2、执行注销
try {
subject.logout();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
return "login";
}
}
}

8、编写数据访问接口UserDao.java

 package cn.temptation.dao;

 import cn.temptation.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; public interface UserDao extends JpaRepository<User, Integer> {
// 根据账号查询用户
@Query(value = "SELECT * FROM sys_user WHERE username=:username", nativeQuery = true)
User findByUsername(@Param("username") String username);
}

9、项目结构

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

10、运行效果

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限的更多相关文章

  1. 【原】无脑操作:IDEA &plus; maven &plus; Shiro &plus; SpringBoot &plus; JPA &plus; Thymeleaf实现基础授权权限

    上一篇<[原]无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限>介绍了实现Shiro的基础认证.本篇谈谈实现 ...

  2. 【原】无脑操作:EasyUI Tree实现左键只选择叶子节点、右键浮动菜单实现增删改

    Easyui中的Tree组件使用频率颇高,经常遇到的需求如下: 1.在树形结构上,只有叶子节点才能被选中,其他节点不能被选中: 2.在叶子节点上右键出现浮动菜单实现新增.删除.修改操作: 3.在非叶子 ...

  3. 【原】无脑操作:express &plus; MySQL 实现CRUD

    基于node.js的web开发框架express简单方便,很多项目中都在使用.这里结合MySQL数据库,实现最简单的CRUD操作. 开发环境: IDE:WebStorm DB:MySQL ------ ...

  4. 【原】无脑操作:eclipse &plus; maven搭建SSM框架

    网上看到一些Spring + Spring MVC + MyBatis框架的搭建教程,不是很详细或是时间久远了,自己动手整一个简单无脑的! 0.系统环境 1)Windows 10 企业版 2)JDK ...

  5. 【原】无脑操作:ElasticSearch学习笔记(01)

    开篇来自于经典的“保安的哲学三问”(你是谁,在哪儿,要干嘛) 问题一.ElasticSearch是什么?有什么用处? 答:截至2018年12月28日,从ElasticSearch官网(https:// ...

  6. Springboot&plus;JPA&plus;Thymeleaf 校园博客完整小网站

    本文所属[知识林]:http://www.zslin.com/web/article/detail/35 此项目是一个比较简易的校园博客.麻雀虽小五脏俱全,虽然是比较简易的但是涉及的知识点还是比较全面 ...

  7. 【原】无脑操作:IDEA &plus; maven &plus; SpringBoot &plus; JPA &plus; Thymeleaf实现CRUD及分页

    一.开发环境: 1.windows 7 企业版 2.IDEA 14 3.JDK 1.8 4.Maven 3.5.2 5.MariaDB 6.SQLYog 二.Maven设置: Maven目录下的con ...

  8. 【原】无脑操作:IDEA &plus; maven &plus; SpringBoot &plus; JPA &plus; EasyUI实现CRUD及分页

    背景:上一篇文章的界面太丑.没有条件查询功能.所以做一些改进,整合EasyUI做实现.(仅以此文纪念表格中出现的这些朋友工作六周年,祭奠一下逝去的青春^_^) 一.开发环境(参照上一篇文章) 补充:E ...

  9. 【原】无脑操作:eclipse创建maven工程时,如何修改默认JDK版本?

    问题描述:eclipse建立maven项目时,JDK版本默认是1.5,想创建时默认版本设置为1.8,如何修改? 解决方案: 找到本机maven仓库存放位置,比如:${user.home}/.m2/路径 ...

随机推荐

  1. 【Mxnet】----1、使用mxnet训练mnist数据集

    使用自己准备的mnist数据集,将0-9的bmp图像分别放到0-9文件夹下,然后用mxnet训练. 1.制作rec数据集 (1).制作list

  2. Haar-like特征

    参考文献: [1]Viola P, Jones M. Rapid object detection using a boosted cascade of simple features[C]//Com ...

  3. js中如何获取纯正的undefined&quest;

    1.为什么要获取undefined? 因为undefined在javascript中不是保留字,可以被用户当做变量来赋值,这样如果我们后期需要用到undefined来检测一个变量的话,那么检测的值就不 ...

  4. 为VS集成IL环境

    为VS2012集成IL工具 在之前的版本VS2010中,在VS的安装目录下/Tools/IL Disassembler这个工具(IL中间语言查看器),但是我想直接把它集成在VS2012里使用, 操作方 ...

  5. Jq合成事件绑定

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 改进的延时函数Delay(使用MsgWaitForMultipleObjects等待消息或超时的到来)

    解决上一节中延时函数占CPU使用率(达50%)的第二种方法是利用消息机制,通过API函数MsgWaitForMultipleObjects等待消息或超时的到来,从而避免使用循环检测使CPU占用率过高. ...

  7. UVALive 7070 The E-pang Palace(暴力)

    实话说这个题就是个暴力,但是有坑,第一次我以为相含是不行的,结果WA,我加上相含以后还WA,我居然把这两个矩形的面积加在一块了吗,应该取大的那一个啊-- 方法就是枚举对角线,为了让自己不蒙圈,我写了一 ...

  8. CentOS tengine mysql 5&period;7 php 5&period;6

    CentOS 7.x 编译安装 LNMP L 版本是 CentOS 7.x  x64版本, N 我们使用tengine 的最新版本,主要原因是因为tengine 默认支持很多的模块. M 这里我们选用 ...

  9. JPA规范及其它持久层框架

    JPA是一种规范,而hibernate是JPA的一种实现 JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口.J ...

  10. 优雅的封装ajax,含跨域

    之前写过一篇 先定一个小目标,自己封装个ajax,是基于原生js的,也就是jquery中ajax的简化版本实现的思路.众所周知,jquery的ajax是项目中最常用的请求后台的方式,也算是封装的很完美 ...