30.0、spring-boot整合Shiro实现授权功能

30.0、spring-boot整合Shiro实现授权功能

在ShiroConfig.java文件里加上这段代码,完整代码往下滑可查看:

//授权,这利表示访问/user/add必须要有user:add权限才能访问
filterMap.put("/user/toadd","perms[user:add]");
filterMap.put("/user/toupdate","perms[user:update]");
//访问的页面如果未授权,跳转到哪个页面
bean.setUnauthorizedUrl("/unauthorized");

在MyController.java页面加入以下代码,完整代码往下滑查看:

@ResponseBody
@RequestMapping("/unauthorized")
public String unauthorized() {
    return "该页面未授权无法访问";
}

        为了能在UserRealm.java类中的授权方法里能够获取登录时用户的信息(包括权限等信息)

所以UserRealm.java类中的认证方法return new SimpleAuthenticationInfo()里,

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

的第一个参数写为user这样在授权方法里才可以拿到user对象里的信息。

        然后用addStringPermission()方法设置当前用户的权限。

在UserRealm.java文件添加如下代码,完整代码下滑查看:

//SimpleAuthorizationInfo
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前登录的用户对象
Subject subject = SecurityUtils.getSubject();
//拿到User对象
User currentuser = (User) subject.getPrincipal();
//设置当前用户的权限
info.addStringPermission(currentuser.getPermit());

return info;

User.java文件如下:

package com.hkl.pojo;

public class User {
    private int id;
    private String username;
    private String password;
    private String permit;

    public User(int id, String username, String password, String permit) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.permit = permit;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getPermit() {
        return permit;
    }
    public void setPermit(String permit) {
        this.permit = permit;
    }

}

搭建一下环境:

创建一个add.html、update.html 文件,里面内容随便自定义即可

再创建一个login.html文件如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h1>登录</h1>

<hr>

<p th:text="${msg}" style="color: red"></p>

<form th:action="@{/logintoindex}" method="post">

    <input type="text" name="username" placeholder="用户名" /><br>
    <input type="password" name="password" placeholder="密码" /><br>
    <input type="submit" value="登录" /><br>

</form>

</body>
</html>

创建 index.html 文件如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
 
<h1>首页</h1>
<hr>
<a th:href="@{/user/toadd}">进入添加用户界面</a>
<a th:href="@{/user/toupdate}">进入修改用户界面</a>
 
</body>
</html>

完整的UserConfig.java代码如下:

package com.hkl.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 {
    @Bean
    ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifier("getdefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设施安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
            anon:   无需认证就可以访问
            authc:    必须认证了才能访问
            user:   必须拥有 记住我 功能才能用
            perms:    拥有对某个资源的权限才能访问
            role:   拥有某个角色权限才能访问
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        //授权,这利表示访问/user/add必须要有user:add权限才能访问
        filterMap.put("/user/toadd","perms[user:add]");
        filterMap.put("/user/toupdate","perms[user:update]");
        //这里表示所有在user下的访问都必须经过认证才可以
        filterMap.put("/user/*","authc");
        bean.setFilterChainDefinitionMap(filterMap);
        //设置一下如果未授权,跳转到那个页面
        bean.setUnauthorizedUrl("/unauthorized");
        //设置登录页面的url请求
        bean.setLoginUrl("/tologin");
        return bean;
    }
    @Bean
    public DefaultWebSecurityManager getdefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }
    //创建realm对象,需要自定义类:1
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }
}

UserRealm.java完整代码如下:

package com.hkl.config;
import com.hkl.pojo.User;
import com.hkl.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 org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权doGetAuthorizationInfo");
        //SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前登录的用户对象
        Subject subject = SecurityUtils.getSubject();
        //拿到User对象
        User currentuser = (User) subject.getPrincipal();
        //设置当前用户的权限
        info.addStringPermission(currentuser.getPermit());
        return info;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");

        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        User user = userService.queryUserByName(userToken.getUsername());

        //如果用户名不正确
        if(user == null) {//没有这个人
            return null;//return null 的意思就是会抛出异常 UnknownAccountException 用户名不存在
        }
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");//这里有三个对象,分别是获取当前用户的认证,密码,认证名,第一个和第三个可以先省略不懈

    }
}

完整MyController.java代码如下:

package com.hkl.controller;
import com.hkl.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.websocket.server.PathParam;
@Controller
public class MyController {
    @Autowired
    private UserService userService;
    @RequestMapping({"/","/index","index.html"})
    public String toindex(Model model) {
        model.addAttribute("msg","hello world首页");
        return "index";
    }
    @RequestMapping("/user/toadd")
    public String toadd() { 
        return "user/add";
    }  
    @RequestMapping("/user/toupdate")
    public String toupdate() {
        return "user/update";
    }  
    @RequestMapping("/tologin")
    public String tologin() {
        return "login";
    }
    @PostMapping("/logintoindex")
    public String logintoindex(@PathParam("username") String username, @PathParam("password") String password,Model model) {
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try{
            subject.login(token);//执行登录方法,如果没有异常就说明OK了
            return "index";
        }catch (UnknownAccountException e) {//用户名不存在
            model.addAttribute("msg","用户名错误!");
            return "login";
        }catch (IncorrectCredentialsException e) {
            model.addAttribute("msg","密码错误!");
            return "login";
        }
    }
    @ResponseBody
    @RequestMapping("/unauthorized")
    public String unauthorized() {
        return "该页面未授权无法访问"; 
    }
}

数据库如下:

首页和登录测试页面如下所示:

 

 

测试一下先登录小澜用户,然后进入首页点击访问一下add页面和update页面,因为小澜没有任何权限所以增加和修改页面应该都不能访问:

没有权限确实无法访问,然后跳转至该页面

然后来测试一下登录小张用户,进入首页后点击进入update页面确实可以进入,但是没有add权限所以不能进入add页面

 有权限确实访问update页面成功了

最后来梳理一下:

        我们在UserConfig.java文件中设置了只要访问/user/toadd的url,就会被拦然后执行UserRealm.java类里的授权方法,获取当前登录的用户的信息,获取当前用户的权限,然后设置权限,最后设置的权限会与需要的权限进行对比,如果权限不符合就跳转至unauthorization页面,符合权限就放行访问。

还是这个问题:

        如果用户只有add的权限而没有update的权限,那么当这个用户登录进入首页页面的时候应该只显示add添加用户的按钮,而不显示update修改用户的按钮才对。

        那么还是一样我们要实现这个功能就要是整合Thymeleaf

第一步:首先我们导入shiro和thymeleaf的整合相关依赖

<!--整合shiro和thymeleaf-->
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

第二步:在ShiroConfig.java文件中配置一下ShiroDialect这个Bean,完整代码下滑查看:

@Bean
public ShiroDialect getShiroDialect() {
    return new ShiroDialect();
}

第三步:在index.html首页里:

<!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>
</head>
<body>

<h1>首页</h1>
<div th:if="${session.loginUser==null}">
    <a th:href="@{/tologin}">登录</a>
</div>
<hr>
<div shiro:hasPermission="user:add">
    <a th:href="@{/user/toadd}">进入添加用户界面</a>
</div>
<div shiro:hasPermission="user:update">
    <a th:href="@{/user/toupdate}">进入修改用户界面</a>
</div>
</body>
</html>

第四步:在UserRealm.java文件中的认证方法里加入以下代码即可,完整代码下滑查看:

Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
session.setAttribute("loginUser",user);

完整的UserRealm.java文件代码如下:

package com.hkl.config;
import com.hkl.pojo.User;
import com.hkl.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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import java.security.Security;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权doGetAuthorizationInfo");
        //SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //拿到当前登录的用户对象
        Subject subject = SecurityUtils.getSubject();
        //拿到User对象
        User currentuser = (User) subject.getPrincipal();
        //设置当前用户的权限
        info.addStringPermission(currentuser.getPermit());
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了=>认证doGetAuthenticationInfo");
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        User user = userService.queryUserByName(userToken.getUsername());
        //如果用户名不正确
        if(user == null) {//没有这个人
            return null;//return null 的意思就是会抛出异常 UnknownAccountException 用户名不存在
        }

        Subject currentSubject = SecurityUtils.getSubject();
        Session session = currentSubject.getSession();
        session.setAttribute("loginUser",user);

        return new SimpleAuthenticationInfo(user,user.getPassword(),"");//这里有三个对象,分别是获取当前用户的认证,密码,认证名,第一个和第三个可以先省略不懈

    }
}

测试一下:登录小澜用户进入首页确实没有显示任何按钮,因为他没有任何权限

 但是这里【注意】,小澜在数据库中还是得给他随便设置一个权限,不然登陆过会报空指针异常

再测试登录小红:确实根据小红的权限,确实只显示了增加用户的按钮,而并没有显示他没有权限的修改用户按钮如下:

 点击进入也确实能够访问add页面:


 

 确实拥有add权限所以成功的访问了add页面

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值