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

需求:

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

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

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

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

分析:

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

关键词汇:

① 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

  1. DROP TABLE sys_user;
  2.  
  3. CREATE TABLE sys_user
  4. (
  5. userid INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
  6. username VARCHAR(10) NOT NULL COMMENT '用户名称',
  7. `password` VARCHAR(10) NOT NULL COMMENT '用户密码'
  8. );
  9.  
  10. INSERT INTO sys_user VALUES(NULL, 'admin', ''), (NULL, 'test', '');
  11.  
  12. SELECT * FROM sys_user;

1、编写项目对象模型文件pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>cn.temptation</groupId>
  8. <artifactId>studyShiro</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10.  
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>2.0.4.RELEASE</version>
  15. </parent>
  16.  
  17. <dependencies>
  18. <!-- web -->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-web</artifactId>
  22. </dependency>
  23. <!-- thymeleaf -->
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  27. </dependency>
  28. <!-- spring data jpa -->
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-data-jpa</artifactId>
  32. </dependency>
  33. <!-- mariadb -->
  34. <dependency>
  35. <groupId>org.mariadb.jdbc</groupId>
  36. <artifactId>mariadb-java-client</artifactId>
  37. <version>2.2.5</version>
  38. </dependency>
  39. <!-- shiro -->
  40. <dependency>
  41. <groupId>org.apache.shiro</groupId>
  42. <artifactId>shiro-spring</artifactId>
  43. <version>1.4.0</version>
  44. </dependency>
  45. <!-- 热启动 -->
  46. <dependency>
  47. <groupId>org.springframework.boot</groupId>
  48. <artifactId>spring-boot-devtools</artifactId>
  49. <optional>true</optional>
  50. </dependency>
  51. </dependencies>
  52. </project>

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

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

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

  1. package cn.temptation;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5.  
  6. @SpringBootApplication
  7. public class Application {
  8. public static void main(String[] args) {
  9. // SpringBoot项目启动
  10. SpringApplication.run(Application.class, args);
  11. }
  12. }

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

登录页面:login.html

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

首页页面:index.html

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

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

配置类ShiroConfig.java

  1. package cn.temptation.shiro;
  2.  
  3. import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  4. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  5. import org.springframework.beans.factory.annotation.Qualifier;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8.  
  9. import java.util.LinkedHashMap;
  10. import java.util.Map;
  11.  
  12. /**
  13. * Shiro配置类
  14. */
  15. @Configuration
  16. public class ShiroConfig {
  17. // 1、创建ShiroFilterFactoryBean
  18. @Bean
  19. public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
  20. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  21. // 设置安全管理器
  22. shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
  23.  
  24. // 设置登录跳转页面
  25. shiroFilterFactoryBean.setLoginUrl("/login");
  26.  
  27. /**
  28. * Shiro内置过滤器:实现权限相关的拦截
  29. * 常用过滤器:
  30. * anon(认证用):无需认证(登录)即可访问
  31. * authc(认证用):必须认证才可访问
  32. * user(少用):使用rememberMe功能可以访问
  33. * perms(授权用):必须得到资源权限才可访问
  34. * role(授权用):必须得到角色权限才可访问
  35. */
  36. Map<String, String> filterMap = new LinkedHashMap<>();
  37.  
  38. // 放行登录请求
  39. filterMap.put("/doLogin", "anon");
  40.  
  41. // 配置退出过滤器,退出代码Shiro已经实现
  42. filterMap.put("/logout", "logout");
  43.  
  44. // 过滤链定义,从上向下顺序执行,一般将/*放在最下边
  45. filterMap.put("/*", "authc");
  46.  
  47. shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
  48.  
  49. return shiroFilterFactoryBean;
  50. }
  51.  
  52. // 2、创建DefaultWebSecurityManager
  53. @Bean(name = "securityManager")
  54. public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm) {
  55. DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
  56.  
  57. // 关联Realm
  58. defaultWebSecurityManager.setRealm(myRealm);
  59.  
  60. return defaultWebSecurityManager;
  61. }
  62.  
  63. // 3、创建Realm
  64. @Bean(name = "myRealm")
  65. public MyRealm getRealm() {
  66. return new MyRealm();
  67. }
  68. }

自定义Realm类MyRealm.java

  1. package cn.temptation.shiro;
  2.  
  3. import cn.temptation.dao.UserDao;
  4. import cn.temptation.domain.User;
  5. import org.apache.shiro.authc.*;
  6. import org.apache.shiro.authz.AuthorizationInfo;
  7. import org.apache.shiro.realm.AuthorizingRealm;
  8. import org.apache.shiro.subject.PrincipalCollection;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10.  
  11. /**
  12. * 自定义Realm
  13. */
  14. public class MyRealm extends AuthorizingRealm {
  15. @Autowired
  16. private UserDao userDao;
  17.  
  18. // 授权处理
  19. @Override
  20. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  21. return null;
  22. }
  23.  
  24. // 认证处理
  25. @Override
  26. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  27. // 编写Shiro判断逻辑,判断账号和密码
  28. // 1、判断账号
  29. UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
  30.  
  31. User user = userDao.findByUsername(token.getUsername());
  32. if (user == null) {
  33. // 账号错误,Shiro底层会抛出UnknownAccountException异常
  34. return null;
  35. }
  36.  
  37. // 2、判断密码
  38. return new SimpleAuthenticationInfo("", user.getPassword(), "");
  39. }
  40. }

6、编写实体类User.java

  1. package cn.temptation.domain;
  2.  
  3. import javax.persistence.*;
  4.  
  5. @Entity
  6. @Table(name = "sys_user")
  7. public class User {
  8. @Id
  9. @GeneratedValue(strategy = GenerationType.IDENTITY)
  10. @Column(name = "userid")
  11. private Integer userid;
  12.  
  13. @Column(name = "username")
  14. private String username;
  15.  
  16. @Column(name = "password")
  17. private String password;
  18.  
  19. public Integer getUserid() {
  20. return userid;
  21. }
  22.  
  23. public void setUserid(Integer userid) {
  24. this.userid = userid;
  25. }
  26.  
  27. public String getUsername() {
  28. return username;
  29. }
  30.  
  31. public void setUsername(String username) {
  32. this.username = username;
  33. }
  34.  
  35. public String getPassword() {
  36. return password;
  37. }
  38.  
  39. public void setPassword(String password) {
  40. this.password = password;
  41. }
  42. }

7、编写控制器类UserController.java

  1. package cn.temptation.web;
  2.  
  3. import org.apache.shiro.SecurityUtils;
  4. import org.apache.shiro.authc.IncorrectCredentialsException;
  5. import org.apache.shiro.authc.UnknownAccountException;
  6. import org.apache.shiro.authc.UsernamePasswordToken;
  7. import org.apache.shiro.subject.Subject;
  8. import org.springframework.stereotype.Controller;
  9. import org.springframework.ui.Model;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11.  
  12. @Controller
  13. public class UserController {
  14. // 访问登录页
  15. @RequestMapping("/login")
  16. public String login() {
  17. return "login";
  18. }
  19.  
  20. // 访问首页
  21. @RequestMapping("/index")
  22. public String index() {
  23. return "index";
  24. }
  25.  
  26. // 登录处理
  27. @RequestMapping("/doLogin")
  28. public String doLogin(String username, String password, Model model) {
  29. // 使用Shiro编写认证处理
  30. // 1、获取Subject
  31. Subject subject = SecurityUtils.getSubject();
  32.  
  33. // 2、封装用户数据
  34. UsernamePasswordToken token = new UsernamePasswordToken(username, password);
  35.  
  36. // 3、执行登录
  37. try {
  38. // 登录成功
  39. subject.login(token);
  40.  
  41. // 返回当前用户的帐号
  42. model.addAttribute("currentuser", token.getUsername());
  43.  
  44. return "index";
  45. } catch (UnknownAccountException exception) {
  46. // 返回错误信息
  47. model.addAttribute("msg", "账号错误!");
  48.  
  49. return "login";
  50. } catch (IncorrectCredentialsException exception) {
  51. // 返回错误信息
  52. model.addAttribute("msg", "密码错误!");
  53.  
  54. return "login";
  55. }
  56. }
  57.  
  58. // 注销处理
  59. @RequestMapping("/doLogout")
  60. public String doLogout() {
  61. // 1、获取Subject
  62. Subject subject = SecurityUtils.getSubject();
  63.  
  64. // 2、执行注销
  65. try {
  66. subject.logout();
  67. } catch (Exception ex) {
  68. ex.printStackTrace();
  69. } finally {
  70. return "login";
  71. }
  72. }
  73. }

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

  1. package cn.temptation.dao;
  2.  
  3. import cn.temptation.domain.User;
  4. import org.springframework.data.jpa.repository.JpaRepository;
  5. import org.springframework.data.jpa.repository.Query;
  6. import org.springframework.data.repository.query.Param;
  7.  
  8. public interface UserDao extends JpaRepository<User, Integer> {
  9. // 根据账号查询用户
  10. @Query(value = "SELECT * FROM sys_user WHERE username=:username", nativeQuery = true)
  11. User findByUsername(@Param("username") String username);
  12. }

9、项目结构

10、运行效果

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

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

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

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

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

  3. 【原】无脑操作:express + MySQL 实现CRUD

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

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

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

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

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

  6. Springboot+JPA+Thymeleaf 校园博客完整小网站

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

  7. 【原】无脑操作:IDEA + maven + SpringBoot + JPA + 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 + maven + SpringBoot + JPA + EasyUI实现CRUD及分页

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

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

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

随机推荐

  1. 远程备份binlog服务

    Ⅰ.bonlog server介绍 对于binlog的备份,之前文章里说的是有从机,一般不备份,那现在人家就是 要备份嘛,怎么办嘛, 写个脚本每天夜里去把前一天产生的binlog拷贝出来可以不? 行啊 ...

  2. 【数据结构】B-Tree, B+Tree, B*树介绍

    [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tree索引,InnoDB还支持B+Tree索引,Memory ...

  3. java基础之接口(抽象类与接口的区别)

    概述 猫狗案例,我们想想狗一般就是看门,猫一般就是作为宠物了,对不.但是,现在有很多的驯养员或者是驯的,这应该属于经过特殊的培训训练出来的,对不.所以,这些额外的动作定义到动物类中就不合适,也不适合直 ...

  4. 整合 ucenter 注册自动激活

    http://my.oschina.net/banbo/blog/311691 应用整合 UCenter,同步注册到 Discuz 的用户,在 Discuz 登录时得手动激活,用户体验很不好,不过解决 ...

  5. 26.app后端怎么架设推送服务

    推送服务已经是app的标配了.架设推送服务,除了可以使用第三方服务商外,也有大量的开源技术可以选择. 现在推送主要分两块,android推送和ios推送,在下面分别论述: 1.    Android推 ...

  6. 跟我学ASP.NET MVC之二:第一个ASP.NET MVC程序

    摘要: 本篇文章带你一步一步创建一个简单的ASP.NET MVC程序.  创建新ASP.NET MVC工程 点击“OK”按钮后,打开下面的窗口: 这里选择“Empty”模板以及“MVC”选项.这次不创 ...

  7. Mac下将文件复制到移动硬盘

    在Mac下将移动硬盘格式化成exfat,这样Mac和Windows都可以对移动硬盘进行识别

  8. 用beego开发服务端应用

    用beego开发服务端应用 说明 Quick Start 安装 创建应用 编译运行 打包发布 代码生成 开发文档 目录结构说明 使用配置文件 beego默认参数 路由设置 路由的表述方式 直接设置路由 ...

  9. bzoj 3343 教主的魔法 分块

    修改直接对整块打标记,两边暴力. 查询需要保证每个整块有序,所以在修改时排序就好啦 #include<cstdio> #include<cstring> #include< ...

  10. BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元

    BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...