博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限
阅读量:6687 次
发布时间:2019-06-25

本文共 12104 字,大约阅读时间需要 40 分钟。

开发环境搭建参见《

需求:

① 除了登录页面,在地址栏直接访问其他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', '123'), (NULL, 'test', '456');11 12 SELECT * FROM sys_user;

 

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

1 
2
5
4.0.0
6 7
cn.temptation
8
studyShiro
9
1.0-SNAPSHOT
10 11
12
org.springframework.boot
13
spring-boot-starter-parent
14
2.0.4.RELEASE
15
16 17
18
19
20
org.springframework.boot
21
spring-boot-starter-web
22
23
24
25
org.springframework.boot
26
spring-boot-starter-thymeleaf
27
28
29
30
org.springframework.boot
31
spring-boot-starter-data-jpa
32
33
34
35
org.mariadb.jdbc
36
mariadb-java-client
37
2.2.5
38
39
40
41
org.apache.shiro
42
shiro-spring
43
1.4.0
44
45
46
47
org.springframework.boot
48
spring-boot-devtools
49
true
50
51
52

 

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.HikariDataSource10 spring.datasource.hikari.minimum-idle=511 spring.datasource.hikari.maximum-pool-size=1512 spring.datasource.hikari.auto-commit=true13 spring.datasource.hikari.idle-timeout=3000014 spring.datasource.hikari.pool-name=DatebookHikariCP15 spring.datasource.hikari.max-lifetime=180000016 spring.datasource.hikari.connection-timeout=3000017 spring.datasource.hikari.connection-test-query=SELECT 118 # Spring Data JPA配置19 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect20 spring.jpa.properties.hibernate.hbm2ddl.auto=update21 spring.jpa.show-sql=true22 spring.jpa.properties.hibernate.format_sql=true23 # 格式化输出的json字符串24 spring.jackson.serialization.indent_output=true25 # 设置控制台彩色打印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  2  3  4     
5 系统登录 6 7 8
9
10 帐号:
11 密码:
12
 
13
14 15

首页页面:index.html

1  2  3  4     
5 系统首页 6 7 8
9
10 11

 

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 @Configuration16 public class ShiroConfig {17     // 1、创建ShiroFilterFactoryBean18     @Bean19     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
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、创建DefaultWebSecurityManager53 @Bean(name = "securityManager")54 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm) {55 DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();56 57 // 关联Realm58 defaultWebSecurityManager.setRealm(myRealm);59 60 return defaultWebSecurityManager;61 }62 63 // 3、创建Realm64 @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  * 自定义Realm13  */14 public class MyRealm extends AuthorizingRealm {15     @Autowired16     private UserDao userDao;17 18     // 授权处理19     @Override20     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {21         return null;22     }23 24     // 认证处理25     @Override26     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 @Controller13 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、获取Subject31         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、获取Subject62         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
{ 9 // 根据账号查询用户10 @Query(value = "SELECT * FROM sys_user WHERE username=:username", nativeQuery = true)11 User findByUsername(@Param("username") String username);12 }

 

9、项目结构

 

10、运行效果

转载于:https://www.cnblogs.com/iflytek/p/9842269.html

你可能感兴趣的文章
向div添加圆角边框
查看>>
马斯克的另一番“威胁论”:人类将成为人工智能的“宠物”
查看>>
逸鹏说道:漫漫人生路
查看>>
Python 正则表达式(字符)详解
查看>>
微信小程序开发工具使用简介
查看>>
基于云计算的软件是否适合企业不同需求?
查看>>
Slab,小对象也能搞出大事情
查看>>
Kali Linux 网络扫描秘籍 第三章 端口扫描(一)
查看>>
6大历史遗留问题,将被区块链技术解决
查看>>
锐捷网络中标农行全国WLAN项目 助推“网点优势“转为“网络优势”
查看>>
万向区块链实验室董事长肖风:区块链经济才是真正的共享经济
查看>>
英伟达VR:GPU的发展还需要一个20年
查看>>
拿什么拯救你——王阿姨的少女心!
查看>>
共享单车步入物联网军备战
查看>>
斯坦福 CS183c 闪电式扩张(Blitzscaling)中文笔记
查看>>
MySQL时间戳与日期互转
查看>>
摘下月亮送给爱人?AstroReality用AR技术帮你实现
查看>>
PHP 魔术变量
查看>>
推荐的PHP编码规范
查看>>
从Linley Group预测报告看物联网四大趋势
查看>>