2024.5.22 Wednesday
Continued from 【WEEK13】 【DAY2】Shiro Part 2【English Version】
15.4. Login Interception
15.4.1. Modifying ShiroConfig.java
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.HashMap;
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 the source code of ShiroFilterFactoryBean to view
// Set the security manager
bean.setSecurityManager(defaultWebSecurityManager);
// Add Shiro's built-in filters
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/add","authc");
filterMap.put("/user/update","authc");
// After modifying the access permissions for the add and update pages here, restart the project. Clicking on add or update will be intercepted, showing a 404 error, and should redirect to the login page
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}
// DefaultWebSecurityManager
...
}
- anon: Accessible without authentication
- authc: Requires authentication
- user: Requires the remember me feature
- perms: Requires permission for a specific resource
- role: Requires a certain role permission
15.4.2. Creating login.html Page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Login</h1>
<hr>
<form action="">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="text" name="password"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
15.4.3. Modifying MyController.java
Adding a method to access the login page
package com.P40.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@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";
}
}
15.4.4. Further Modification to ShiroConfig.java
Using wildcards to redirect to the login page
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 the source code of ShiroFilterFactoryBean to view
// Set the security manager
bean.setSecurityManager(defaultWebSecurityManager);
// Add Shiro's built-in filters
/*
anon: Accessible without authentication
authc: Requires authentication
user: Requires the remember me feature
perms: Requires permission for a specific resource
role: Requires a certain role permission
*/
// Login interception
Map<String,String> filterMap = new LinkedHashMap<>();
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
// After modifying the access permissions for the add and update pages here, restart the project. Clicking on add or update will be intercepted, showing a 404 error, and should redirect to the login page
filterMap.put("/user/*","authc"); // Wildcards can also be used to achieve the same effect as the above two lines (/user/add and /user/update)
bean.setFilterChainDefinitionMap(filterMap);
// If there is no permission, it needs to be redirected to the login page
bean.setLoginUrl("/toLogin"); // Set the login request
return bean;
}
// DefaultWebSecurityManager
@Bean(name = "securityManager") // Assign an alias to this class for easy reference by ShiroFilterFactoryBean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ // Get UserRealm, but it seems that annotations are not needed here and can be called directly
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// The default class name of DefaultWebSecurityManager is defaultWebSecurityManager, but it is changed to securityManager here
// Associate UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
// Create realm object, need to customize the class
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
// The creation order is reversed (from realm->DefaultWebSecurityManager->ShiroFilterFactoryBean)
}
15.4.5. Restart
Click add or update on the homepage to jump to the login page
http://localhost:8080/toLogin
15.5. User Authentication
15.5.1. Modifying 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;
@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 user 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) { // Incorrect password
model.addAttribute("msg","Incorrect password");
return "login";
}
}
}
15.5.2.Modifying login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Login</h1>
<hr>
<p th:text="${msg}" style="color: cadetblue"></p>
<form th:action="@{/login}">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="text" name="password"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
15.5.3. Restart
Enter any username and password
It indicates that the execution was successful
15.5.4. Modify UserRealm.java
package com.P40.config;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
// UserRealm is a bean
// Custom UserRealm, you must inherit the AuthorizingRealm method, and then implement methods (alt+insert)
public class UserRealm extends AuthorizingRealm {
// Authorization
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("do doGetAuthorizationInfo Authorization");
return null;
}
// Authentication
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("do doGetAuthorizationInfo Authentication");
// Username, password————data retrieval
String name = "root";
String password = "1";
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
if (!userToken.getUsername().equals(name)){
return null; // Throw UnknownAccountException automatically
}
// Password authentication, shiro operation
return new SimpleAuthenticationInfo("",password,"");
}
}
15.5.5. Restart
Select add or update to click, and automatically jump to the login page.
15.5.5.1. Enter the correct username and password
After submission, return to the homepage, and both the add and update pages can be accessed
15.5.5.2. Enter the wrong username
15.5.5.3. Enter the wrong password