springboot集成shiro安全框架

2 篇文章 0 订阅
1 篇文章 0 订阅

        Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

一、引入maven配置

1

2

3

4

5

<dependency>

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

    <artifactId>shiro-spring</artifactId>

    <version>1.4.0</version>

</dependency>

二、建表

用户表、角色表、权限表、用户角色表、角色权限表。

权限表:news:* 表示有新闻的所有权限(包括增删改查),而news:add,只有新闻的新增权限。

用户角色表:用户拥有哪些角色。

角色权限表:角色拥有哪些权限。

三、自定义Realm

自定义realm主要用于用户的权限验证以及登录验证。

自定义realm继承AuthorizingRealm类,并重写doGetAuthorizationInfo和doGetAuthenticationInfo方法,doGetAuthorizationInfo方法主要校验用户的权限,即该用户拥有什么角色以及权限。doGetAuthenticationInfo用于校验登录验证,即用户的用户名或者密码是否正确。

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

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

/**

 * 类名 : shiro的Realm

 * 用法 :

 * 创建人 : shyroke

 * 时间:2018/12/12 17:29

 */

public class MyRealm extends AuthorizingRealm {

    @Autowired

    private UserMapper userMapper;

    @Autowired

    private PermissionMapper permissionMapper;

    /**

     * 授权,即该用户拥有什么角色以及权限

     * 步骤:根据用户名获取角色以及权限,然后设置到验证信息类并返回。

     * @param principalCollection

     * @return

     */

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        String userName = principalCollection.getPrimaryPrincipal().toString();

//        获取该用户的角色

        List<Role> roles = userMapper.getRolesByUserName(userName);

        Set<String> roleSets = new HashSet<>();

//        获取该用户的权限集

        List<Permission> permissions = new ArrayList<>();

        Set<String> permissoinSet = new HashSet<>();

        //将List转为Set

        if(roles !=null && roles.size()>0){

            for(Role role:roles){

                roleSets.add(role.getName());

                permissions.addAll(permissionMapper.getPermissionByRoleId(role.getId()));

            }

        }

        //将List转为Set

        if(permissions!=null & permissoinSet.size()>0){

            for(Permission p :permissions){

                permissoinSet.add(p.getName());

            }

        }

        info.addRoles(roleSets);

        info.addStringPermissions(permissoinSet);

        return info;

    }

    /**

     * 认证,即用户账号密码是否正确

     * @param token

     * @return

     * @throws AuthenticationException

     */

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

//        获取用户名和密码

        String userName = (String)token.getPrincipal();

        String passWord = new String((char[]) token.getCredentials());

//        根据用户名查找该用户

        User user =  userMapper.getUserByName(userName);

        if(user == null){

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

        }

        if(!user.getPassword().equals(passWord)){

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

        }

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

        return info;

    }

}

四、shiro配置类

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

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

/**

 * 类名 :shiro的核心配置类

 * 用法 :

 * 创建人 : shyroke

 * 时间:2018/12/14 15:20

 */

@Configuration

public class ShiroConfigration {

//    设置自定义Realm

    @Bean

    public MyRealm myRealm(){

        return new MyRealm();

    }

//    权限管理,配置主要是Realm的管理认证

    @Bean

    public SecurityManager securityManager(){

        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();

        manager.setRealm(myRealm());

        return manager;

    }

    /**

     * 设置过滤条件和跳转条件

     * anon 不生效的原因:1、map的类型必须是LinkedHashMap 2、anon必须定义在authc之前

     *

     * @param securityManager

     * @return

     */

    @Bean

        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){

            ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

            factoryBean.setSecurityManager(securityManager);

//            设置登录跳转

            factoryBean.setLoginUrl("/admin");

            factoryBean.setSuccessUrl("/admin/index");

            //必须为LinkedHashMap 否则anon不生效

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

            //退出

            map.put("/admin/logout","logout");

            //登录页面和登录验证不要拦截

            map.put("/admin/login.html","anon");

            map.put("/admin/tologin","anon");

            //设置需要过滤的链接

            map.put("/admin/**","authc");

            factoryBean.setFilterChainDefinitionMap(map);

            return factoryBean;

        }

    /**

     *  开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证

     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能

     @return

     */

    @Bean

    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){

        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();

        advisorAutoProxyCreator.setProxyTargetClass(true);

        return advisorAutoProxyCreator;

    }

    /**

     * 开启aop注解支持

     * @param securityManager

     * @return

     */

    @Bean

    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {

        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();

        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

        return authorizationAttributeSourceAdvisor;

    }

}

五、调用

代码如下,当调用Subject.login方法后,会调用自定义Realm的doGetAuthenticationInfo方法校验用户名密码是否正确,如果不正确则抛出对应异常,controller层捕获并处理异常。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

AuthenticationToken usernamePasswordToken = new UsernamePasswordToken(user.getName(),user.getPassword());

Subject subject = SecurityUtils.getSubject();

try {

    subject.login(usernamePasswordToken);

}catch (UnknownAccountException ex) {

    logger.info("用户名错误!");

    return R.error("用户名错误!");

catch (IncorrectCredentialsException ex) {

    logger.info("密码错误!");

    return R.error("密码错误!");

catch (AuthenticationException ex) {

    logger.info(ex.getMessage());

    return R.error("系统错误,请查看日志");

catch (Exception ex) {

    logger.info(ex.getMessage());

    return R.error("系统错误,请查看日志");

}

#@lehao#

帮助到您请点赞关注收藏谢谢!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@lehao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值