89.【SpringBoot-02】(十)

简介: 89.【SpringBoot-02】
(5).授权功能的实现

去到ShiroConfig.java中,添加代码,注意要添加在(顺序)

filterMap.put("/add","perms[user:add]");
        filterMap.put("/add.html","perms[user:add]");

之后我们执行I一下发现登陆后add标签也无权访问

显示401的意思就是未授权

当然正常的是要访问无权限页面的(授权要写在认证的前面)

package com.jsxs.config;
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;
@Configuration
public class ShiroConfig {
    // ShiroFilterFactoryBean   ----》 Subject
    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ // 通过注解指定是 public DefaultWebSecurityManager getDefaultWebSecurityManager 这个Bean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);  //设置安全管理器
        /**
        *   anno :无需认证就可以访问
         *   authc : 必须认证了才能访问
         *   user :必须拥有 记住我 功能才有用
         *   perms : 拥有对某个资源的权限才能访问
         *   role : 拥有某个角色权限次啊能使用
         */
        //  拦截
        //  认证才能访问
        Map<String, String> filterMap = new LinkedHashMap<>();//
        filterMap.put("/add","perms[user:add]");
        filterMap.put("/add.html","perms[user:add]");
        filterMap.put("/update","authc");
        filterMap.put("/update.html","authc");
        // 授权才能访问
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);  //这个一定要添加
        //假如说没有认证/授权我们就会走这个路径
        shiroFilterFactoryBean.setLoginUrl("/toLogin");  //假如说没有权限/认证我们就会走这个路径
        //假如说此用户没有授权我们就会走如下的页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        return shiroFilterFactoryBean;
    }
    //DefaultWebSecurityManger  ----》 SecurityManger ---->02
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){  // 通过注解指定是 public UserRealm  userRealm() 这个Bean
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);  //进行关联 Realm
        return defaultWebSecurityManager;
    }
    //创建 Realm 对象 ----》 Realm  需要自定义----> 01
    @Bean(name = "userRealm")
    public UserRealm  userRealm(){
        return new UserRealm();
    }
}

接下来我们去UserRealm中给添加权限,注意不要导错类SimpleAuthorizationInfo

//  授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=》授权的方法");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");   //给用户添加这个权限
        return info;
    }
package com.jsxs.config;
import com.jsxs.pojo.User;
import com.jsxs.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import javax.annotation.Resource;
public class UserRealm extends AuthorizingRealm {
    //  授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=》授权的方法");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("user:add");   //给用户添加这个权限
        return info;
    }
    //我们需要添加业务层的支持
    @Resource
    UserService userService;
    //  认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=》认证的方法");
        // 链接虚拟的数据库
 //       String name = "admin";
  //      String password = "123456";
        //  链接真实的数据库
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user = userService.queryByName(userToken.getUsername());   //获取前端的名字,通过前端的截取的用户名进行查询
        if (user==null) {   // 假如说查询的user为空,那么就返回null
            return null;  // 抛出异常 UnknownAccount
        }
        //  密码认证 ----》Shiro帮我们做
        return new SimpleAuthenticationInfo("",user.getPwd(),"");
    }
}

诶,接下来所有用户就都有这个权限

但是不想让所有用户都有某个权限要怎么实现呢?

首先先去数据表中添加一个权限字段

并且要记得修改pojo实体类

package com.jsxs.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
    private String perms;
}

ok数据层完毕,接下来要思考,我们想要获取到用户的权限,但是获取用户是在刚刚认证中通过userservice获取的,

在认证里面查到的东西我们怎么放到授权中去呢?

想到了两个:①session ②用户当前对象的属性来取get方法或(点属性)

我们在认证中,最后new了一个SimpleAuthenticationInfo的当前认证对象,之前里面要传递三个参数分别为:

(资源,密码,realmName)

我们把获取到的user传入到资源中去。

return new SimpleAuthenticationInfo(user,user.getPwd(),"");

这样一来,user这个资源就传递到了当前用户subject整体资源中,通过当前subject获取资源来获取到这个user

所以在授权的功能中要先获取subject当前用户

Subject subject = SecurityUtils.getSubject();

然后通过subject获取到资源

User currentUser = (User) subject.getPrincipal();

再给当前用户添加user中对应的权限名,注意方法名是addStringPermission权限

info.addStringPermission(currentUser.getPerms());

最后返回当前权限info

package com.jsxs.config;
import com.jsxs.pojo.User;
import com.jsxs.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import javax.annotation.Resource;
public class UserRealm extends AuthorizingRealm {
    //  授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=》授权的方法");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //info.addStringPermission("user:add");   //给所有用户添加这个权限
        //拿到当前登入的这个对象
        Subject subject = SecurityUtils.getSubject();
        // 获取共享的数据--->拿到User对象
        User currentUser = (User) subject.getPrincipal();
        // 通过查询当前的数据库信息,设定当前用户的权限
        info.addStringPermission(currentUser.getPerms());
        return info;
    }
    //我们需要添加业务层的支持
    @Resource
    UserService userService;
    //  认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了=》认证的方法");
        // 链接虚拟的数据库
 //       String name = "admin";
  //      String password = "123456";
        //  链接真实的数据库
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user = userService.queryByName(userToken.getUsername());   //获取前端的名字,通过前端的截取的用户名进行查询
        if (user==null) {   // 假如说查询的user为空,那么就返回null
            return null;  // 抛出异常 UnknownAccount
        }
        //  密码认证 ----》Shiro帮我们做
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");  //------->这里我们为第一个参数赋值,目的就是我们可以共享这个资源
    }
}

退出功能就和之前security的logout一样,设置一下退出的路径就可

好现在基本需求都完了,但是想和之前security一样实现没有权限的就不要显示,就需要和thymeleaf结合

(6).Shiro和thymeleaf整合

首先要导入shrio和thymeleaf结合的依赖

<!-- https://mvnrepository.com/artifact/com.github.theborakompanioni/thymeleaf-extras-shiro -->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

ok接下来就要去前端页面编写标签了,之前在security中用到的是sec,这里用的shiro,当然也要导入命名空间

下面是spring-security的命名空间

xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"

shiro的:

xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"

或则

推荐

xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"

前端代码:

假如说存在权限add我们就显示,不存在的话就不显示

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"
>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<p>
    <a th:href="@{/toLogin}">登入</a>
</p>
<p th:text="${msg}"></p>
<hr>
<div shiro:hasPermission="user:add">
    <a th:href="@{/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/update}">update</a>
</div>
</body>
</html>

登录按钮无权限时显示:

<div shiro:notAuthenticated>
    <a th:href="@{/toLogin}">登录</a>
</div>

相关文章
|
SQL Java 数据库连接
|
存储 缓存 安全
89.【SpringBoot-02】(六)
89.【SpringBoot-02】
54 0
|
4月前
|
Java 应用服务中间件 Maven
|
5月前
springboot2.4.5使用fastjosn
springboot2.4.5使用fastjosn
|
XML Java 数据库连接
89.【SpringBoot-02】(三)
89.【SpringBoot-02】
55 0
|
JSON JavaScript Java
87.【SpringBoot-01】(七)
87.【SpringBoot-01】
59 0
|
监控 Java
SpringBoot
springBoot
209 0
|
存储 开发框架 Java
《SpringBoot篇》19.SpringBoot整合Quart
《SpringBoot篇》19.SpringBoot整合Quart
369 0
《SpringBoot篇》19.SpringBoot整合Quart
|
Java Spring
springboot 小记
springboot 小记
|
XML JavaScript Java
SpringBoot(一):什么是SpringBoot?
SpringBoot(一):什么是SpringBoot?
443 0