好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Springboot整合Shiro实现登录与权限校验详细解读

Springboot-cli 开发脚手架系列

Springboot优雅的整合Shiro进行登录校验,权限认证(附源码下载)

简介

Springboo配置Shiro进行登录校验,权限认证,附demo演示。

前言

我们致力于让开发者快速搭建基础环境并让应用跑起来,提供使用示例供使用者参考,让初学者快速上手。

本博客项目源码地址:

项目源码github地址

项目源码国内gitee地址

1. 环境

依赖

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

<!-- Shiro核心框架 -->

    < dependency >

        < groupId >org.apache.shiro</ groupId >

        < artifactId >shiro-core</ artifactId >

        < version >1.9.0</ version >

    </ dependency >

    <!-- Shiro使用Spring框架 -->

    < dependency >

        < groupId >org.apache.shiro</ groupId >

        < artifactId >shiro-spring</ artifactId >

        < version >1.9.0</ version >

    </ dependency >

    <!-- Thymeleaf中使用Shiro标签 -->

    < dependency >

        < groupId >com.github.theborakompanioni</ groupId >

        < artifactId >thymeleaf-extras-shiro</ artifactId >

        < version >2.1.0</ version >

    </ dependency >

    < dependency >

        < groupId >org.springframework.boot</ groupId >

        < artifactId >spring-boot-starter-thymeleaf</ artifactId >

    </ dependency >

yml配置

server:
  port: 9999
  servlet:
    session:
      # 让Tomcat只能从COOKIE中获取会话信息,这样,当没有Cookie时,URL也就不会被自动添加上 ;jsessionid=… 了。
      tracking-modes: COOKIE

spring:
  thymeleaf:
    # 关闭页面缓存,便于开发环境测试
    cache: false
    # 静态资源路径
    prefix: classpath:/templates/
    # 网页资源默认.html结尾
    mode: HTML
 

2. 简介

Shiro三大功能模块

Subject

认证主体,通常指用户(把操做交给SecurityManager)。

SecurityManager

安全管理器,安全管理器,管理全部Subject,能够配合内部安全组件(关联Realm)

Realm

域对象,用于进行权限信息的验证,shiro连接数据的桥梁,如我们的登录校验,权限校验就在Realm进行定义。

3. Realm配置

定义用户实体User ,可根据自己的业务自行定义

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@Data

@Accessors (chain = true )

public class User {

     /**

      * 用户id

      */

     private Long userId;

     /**

      * 用户名

      */

     private String username;

     /**

      * 密码

      */

     private String password;

     /**

      * 用户别称

      */

     private String name;

}

重写AuthorizingRealm 中登录校验doGetAuthenticationInfo及授权doGetAuthorizationInfo方法,编写我们自定义的校验逻辑。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

/**

  * 自定义登录授权

  *

  * @author ding

  */

public class UserRealm extends AuthorizingRealm {

     /**

      * 授权

      * 此处权限授予

      */

     @Override

     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

         // 在这里为每一个用户添加vip权限

         info.addStringPermission( "vip" );

         return info;

     }

     /**

      * 认证

      * 此处实现我们的登录逻辑,如账号密码验证

      */

     @Override

     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

         // 获取到token

         UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

         // 从token中获取到用户名和密码

         String username = token.getUsername();

         String password = String.valueOf(token.getPassword());

         // 为了方便,这里模拟获取用户

         User user = this .getUser();

         if (!user.getUsername().equals(username)) {

             throw new UnknownAccountException( "用户不存在" );

         } else if (!user.getPassword().equals(password)) {

             throw new IncorrectCredentialsException( "密码错误" );

         }

         // 校验完成后,此处我们把用户信息返回,便于后面我们通过Subject获取用户的登录信息

         return new SimpleAuthenticationInfo(user, password, getName());

     }

     /**

      * 此处模拟用户数据

      * 实际开发中,换成数据库查询获取即可

      */

     private User getUser() {

         return new User()

                 .setName( "admin" )

                 .setUserId(1L)

                 .setUsername( "admin" )

                 .setPassword( "123456" );

     }

}

4. 核心配置

ShiroConfig.java

/**

* Shiro内置过滤器,能够实现拦截器相关的拦截器

* 经常使用的过滤器:

* anon:无需认证(登陆)能够访问

* authc:必须认证才能够访问

* user:若是使用rememberMe的功能能够直接访问

* perms:该资源必须获得资源权限才能够访问,格式 perms[权限1,权限2]

* role:该资源必须获得角色权限才能够访问

**/

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

/**

  * shiro核心管理器

  *

  * @author ding

  */

@Configuration

public class ShiroConfig {

     /**

      * 无需认证就可以访问

      */

     private final static String ANON = "anon" ;

     /**

      * 必须认证了才能访问

      */

     private final static String AUTHC = "authc" ;

     /**

      * 拥有对某个资源的权限才能访问

      */

     private final static String PERMS = "perms" ;

     /**

      * 创建realm,这里返回我们上一把定义的UserRealm

      */

     @Bean (name = "userRealm" )

     public UserRealm userRealm() {

         return new UserRealm();

     }

     /**

      * 创建安全管理器

      */

     @Bean (name = "securityManager" )

     public DefaultWebSecurityManager getDefaultWebSecurityManager( @Qualifier ( "userRealm" ) UserRealm userRealm) {

         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

         //绑定realm对象

         securityManager.setRealm(userRealm);

         return securityManager;

     }

     /**

      * 授权过滤器

      */

     @Bean

     public ShiroFilterFactoryBean getShiroFilterFactoryBean( @Qualifier ( "securityManager" ) DefaultWebSecurityManager defaultWebSecurityManager) {

         ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();

         // 设置安全管理器

         bean.setSecurityManager(defaultWebSecurityManager);

         // 添加shiro的内置过滤器

         Map<String, String> filterMap = new LinkedHashMap<>();

         filterMap.put( "/index" , ANON);

         filterMap.put( "/userInfo" , PERMS + "[vip]" );

         filterMap.put( "/table2" , AUTHC);

         filterMap.put( "/table3" , PERMS + "[vip2]" );

         bean.setFilterChainDefinitionMap(filterMap);

         // 设置跳转登陆页

         bean.setLoginUrl( "/login" );

         // 无权限跳转

         bean.setUnauthorizedUrl( "/unAuth" );

         return bean;

     }

     /**

      * Thymeleaf中使用Shiro标签

      */

     @Bean

     public ShiroDialect shiroDialect() {

         return new ShiroDialect();

     }

}

5. 接口编写

IndexController.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

/**

  * @author ding

  */

@Controller

public class IndexController {

     @RequestMapping ({ "/" , "/index" })

     public String index(Model model) {

         model.addAttribute( "msg" , "hello,shiro" );

         return "/index" ;

     }

     @RequestMapping ( "/userInfo" )

     public String table1(Model model) {

         return "userInfo" ;

     }

     @RequestMapping ( "/table" )

     public String table(Model model) {

         return "table" ;

     }

     @GetMapping ( "/login" )

     public String login() {

         return "login" ;

     }

     @PostMapping (value = "/doLogin" )

     public String doLogin( @RequestParam ( "username" ) String username, @RequestParam ( "password" ) String password, Model model) {

         //获取当前的用户

         Subject subject = SecurityUtils.getSubject();

         //用来存放错误信息

         String msg = "" ;

         //如果未认证

         if (!subject.isAuthenticated()) {

             //将用户名和密码封装到shiro中

             UsernamePasswordToken token = new UsernamePasswordToken(username, password);

             try {

                 // 执行登陆方法

                 subject.login(token);

             } catch (Exception e) {

                 e.printStackTrace();

                 msg = "账号或密码错误" ;

             }

             //如果msg为空,说明没有异常,就返回到主页

             if (msg.isEmpty()) {

                 return "redirect:/index" ;

             } else {

                 model.addAttribute( "errorMsg" , msg);

                 return "login" ;

             }

         }

         return "/login" ;

     }

     @GetMapping ( "/logout" )

     public String logout() {

         SecurityUtils.getSubject().logout();

         return "index" ;

     }

     @GetMapping ( "/unAuth" )

     public String unAuth() {

         return "unAuth" ;

     }

}

6. 网页资源

在resources中创建templates文件夹存放页面资源

index.html

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<!DOCTYPE html>

< html xmlns:th = "http://HdhCmsTestthymeleaf.org" >

< html xmlns:shiro = "http://HdhCmsTestpollix.at/thymeleaf/shiro" >

< head >

     < meta charset = "UTF-8" >

     < title >Title</ title >

</ head >

< body >

< h1 >首页</ h1 >

<!-- 使用shiro标签 -->

< shiro:authenticated >

     < p >用户已登录</ p > < a th:href = "@{/logout}" rel = "external nofollow" >退出登录</ a >

</ shiro:authenticated >

< shiro:notAuthenticated >

     < p >用户未登录</ p >  

</ shiro:notAuthenticated >

< br />

< a th:href = "@{/userInfo}" rel = "external nofollow" >用户信息</ a >

< a th:href = "@{/table}" rel = "external nofollow" >table</ a >

</ body >

</ html >

login.html

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<!DOCTYPE html>

< html lang = "en" xmlns:th = "http://HdhCmsTestthymeleaf.org" >

< head >

     < meta charset = "UTF-8" >

     < title >登陆页</ title >

</ head >

< body >

< div >

     < p th:text = "${errorMsg}" ></ p >

     < form action = "/doLogin" method = "post" >

         < h2 >登陆页</ h2 >

         < h6 >账号:admin,密码:123456</ h6 >

         < input type = "text" id = "username"   name = "username" placeholder = "admin" >

         < input type = "password" id = "password" name = "password"   placeholder = "123456" >

         < button type = "submit" >登陆</ button >

     </ form >

</ div >

</ body >

</ html >

userInfo.html

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<!DOCTYPE html>

< html lang = "en" xmlns:shiro = "http://HdhCmsTestpollix.at/thymeleaf/shiro" >

< head >

     < meta charset = "UTF-8" >

     < title >table1</ title >

</ head >

< body >

< h1 >用户信息</ h1 >

<!-- 利用shiro获取用户信息 -->

用户名:< shiro:principal property = "username" />

< br />

用户完整信息: < shiro:principal />

</ body >

</ html >

table.hetml

?

1

2

3

4

5

6

7

8

9

10

<!DOCTYPE html>

< html lang = "en" >

< head >

     < meta charset = "UTF-8" >

     < title >table</ title >

</ head >

< body >

< h1 >table</ h1 >

</ body >

</ html >

7. 效果演示

启动项目浏览器输入 127.0.0.1:9999

当我们点击用户信息和table时会自动跳转登录页面

登录成功后

获取用户信息

此处获取的就是我们就是我们前面doGetAuthenticationInfo方法返回的用户信息,这里为了演示就全部返回了,实际生产中密码是不能返回的。

8. 源码分享

本项目已收录

Springboot-cli开发脚手架,集合各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,帮助初学者快速上手。

项目源码github地址

项目源码国内gitee地址

到此这篇关于Springboot整合Shiro实现登录与权限校验详细分解的文章就介绍到这了,更多相关Springboot Shiro登陆校验内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://blog.csdn.net/dingdingdandang/article/details/124413459

查看更多关于Springboot整合Shiro实现登录与权限校验详细解读的详细内容...

  阅读:18次