【WEEK14】 【DAY1】Shiro Part 6【English Version】

2024.5.27 Monday

15.7. Implementation of Shiro Request Authorization

Continuing from the previous section【WEEK13】 【DAY5】Shiro Part 5【English Version】

15.7.6. Modify Database Related Parameters to Use Real Database Data

15.7.6.1. Modify the Database

In reality, whether a user has access to a particular functionality (page) should be stored in the database. The program should then read it and determine whether the corresponding page is accessible to the specified user. The method of adding authorization using the addStringPermission method in the UserRealm class in the previous section is not reasonable. Also, because the current database lacks a column for user permissions, a new column needs to be added here.
Insert image description here
Insert image description here
Grant permissions to users respectively:
Insert image description here
Lisi and Wangwu have no permissions, and the perms column cannot be left empty directly. It needs to be filled with null or user:null. Otherwise, when attempting to access add or update, the error page that appears is still not the modified prompt statement but the default 401 page.

15.7.6.2. Modify User.java

Add one parameter

package com.P40.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
    private String perms;
}

15.7.7. Modify UserRealm.java

package com.P40.config;

import com.P40.pojo.User;
import com.P40.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;

//UserRealm is a bean
//Customized UserRealm, it must inherit AuthorizingRealm method, and then implement methods (alt+insert)
public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    //Authorization
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("do doGetAuthorizationInfo Authorization");

        //Authorization
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();   //You can first write new SimpleAuthorizationInfo(); and then use Alt+Enter to quickly create the preceding framework
//        info.addStringPermission("user:add");   //Give all logged-in users permission to access User:add, at this time, any logged-in user can access the add page

        //Get the currently logged-in object
        Subject subject = SecurityUtils.getSubject();   //Represents the currently logged-in user
        User currentUser = (User) subject.getPrincipal(); //Take out the first parameter (user) from SimpleAuthenticationInfo(user,user.getPwd(),""); and get the user object
        //Set permissions for the current user
        info.addStringPermission(currentUser.getPerms());

        //Cannot return null
        return info;
    }

    //Authentication
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("do doGetAuthenticationInfo Authentication");

        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;

        //Change to connect to the real database
        User user = userService.queryUserByName(userToken.getUsername());
        if(user == null){   //This user does not exist
            return null;    //UnknownAccountException
        }

        //Password authentication, shiro operation
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}

15.7.8. Modify ShiroConfig.java

Add authorization

package com.P40.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
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //What to configure: click to enter ShiroFilterFactoryBean source code for viewing
        //Set security manager
        bean.setSecurityManager(defaultWebSecurityManager);

        //Add Shiro's built-in filters
        /*
        anon: Allows access without authentication
        authc: Requires authentication to access
        user: Requires the Remember Me function to be enabled
        perms: Requires permission to access a specific resource
        role: Requires permission for a specific role
         */
        //Login interception
        Map<String,String> filterMap = new LinkedHashMap<>();

        //Authorization. Normally, it should redirect to an unauthorized page, but because only the following verifications are added, it leads to direct redirection to the 401 page
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

//        filterMap.put("/user/add","authc");
//        filterMap.put("/user/update","authc");
        //After modifying the access permissions for the add and update pages only here, restart the project, and clicking add or update will be intercepted, showing a 404 error, hoping to redirect to the login page
        filterMap.put("/user/*","authc");   //Wildcards can also be used to achieve (replacing the above two lines of /user/add and /user/update)
        bean.setFilterChainDefinitionMap(filterMap);

        //If no permission, it needs to be redirected to the login page
        bean.setLoginUrl("/toLogin");   //Set the login request

        //Unauthorized page
        bean.setUnauthorizedUrl("/noauth");

        return bean;
    }

    //DefaultWebSecurityManager
    @Bean(name = "securityManager") //Alias this class for easy invocation by ShiroFilterFactoryBean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){    //Get UserRealm, but it seems that annotations are not needed here, and it can be called directly
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //The default class name of DefaultWebSecurityManager is defaultWebSecurityManager, just changed to securityManager here

        //Associate UserRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //Create realm object, need to customize class
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //Creation order is reversed (from real->DefaultWebSecurityManager->ShiroFilterFactoryBean)
}

15.7.9. Add Logout Functionality

15.7.9.1. Modify index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Home</h1>
<p th:text="${msg}"></p>

<hr>    <!--Create a horizontal line in the HTML page-->
<a th:href="@{/user/add}">add</a>  |   <a th:href="@{/user/update}">update</a>
<!--a tag defines a hyperlink for linking from one page to another-->
<hr>
<a class="nav-link" th:href="@{/logout}" onclick="alert('Signed out')">Sign out</a><!--Don't spell href as herf-->

</body>
</html>

15.7.9.2. Modify MyController.java

package com.P40.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

@Controller
public class MyController {

    @RequestMapping({"/", "/index"})
    public String toIndex(Model model){
        model.addAttribute("msg","hello, Shiro");
        return "index";
    }


    @RequestMapping("/user/add")
    public String add(){
        return "user/add";
    }

    @RequestMapping("/user/update")
    public String update(){
        return "user/update";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }


    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        //Get the current user
        Subject subject = SecurityUtils.getSubject();

        //Encapsulate the user's login data
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);

        //Execute the login method, if there is no exception, it is successful, select the code and press Ctrl+Alt+T to add try catch
        try {
            subject.login(token);
            return "index";
        } catch (UnknownAccountException e) {   //Username does not exist
            model.addAttribute("msg","Incorrect username");
            return "login";
        } catch (IncorrectCredentialsException e) {   //Wrong password
            model.addAttribute("msg","Incorrect password");
            return "login";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "Unauthorized, access to this page is forbidden";
    }

    //Logout
    @RequestMapping("/logout")
    public String logout(){
        Subject currentUser = SecurityUtils.getSubject();
        currentUser.logout();
        return "/login";
    }

}

15.7.10. Restart and Verify Permissions for Respective Users and Logout Functionality

15.7.10.1. zhangsan

Login:
Login

Click on “add”:
Add
Add Result

Click on “update”:
Update
Update Result

Click on “Sign out”:
Sign Out
Sign Out Result

15.7.10.2. lisi

Login:
Login

Click on “add”:
Click on “update”:
Update Result

Click on “Sign out”:
Sign Out

15.7.10.3. wangwu

Login:
Login

Click on “add”:
Click on “update”:
Update Result

Click on “Sign out”:
Sign Out

15.7.10.4. root

Login:
Login

Click on “add”:
Add

Click on “update”:
Update

Click on “Sign out”:
Sign Out
Sign Out Result

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值