Marco's Java

Preface

In the previous section, we have constructed the MVC framework of Shiro+SMM integrated Maven project, so this section is to inject "soul" into it, so that the program can run smoothly. Let's continue to follow my thinking.~

SMM and Shiro Integrated Profile

Form 14: Importing configuration files
In fact, so far, the overall framework of our "small project" has been almost built, but the last step left is configuration files. Don't forget to configure the project. As soon as it runs, it cries. Haha, putting the configuration here is mainly to take you through. Know what we have to configure again, otherwise we will be really confused. After reading my previous Spring series of blog posts, my friends should not talk about these configurations.

1)application-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	
	<context:property-placeholder location="classpath:jdbc.properties" system-properties-mode="FALLBACK"/>
	<!-- alibaba Druid Database connection pool -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${driverClassName}"></property>
		<property name="url" value="${url}"></property>
		<property name="username" value="${username}"></property>
		<property name="password" value="${password}"></property>
		<!-- Set the maximum number of connections -->
		<property name="maxActive" value="50"></property>
		<!-- Set initialization number -->
		<property name="initialSize" value="10"></property>
		<!-- Set the maximum waiting time -->
		<property name="maxWait" value="5000"></property>
		<!-- Injection filter, key step, turn on Druid Monitoring and Statistical Function  -->
		<property name="filters" value="stat"></property>
		<!-- How often is the configuration interval detected to detect idle connections that need to be closed in milliseconds? -->
  		<property name="timeBetweenEvictionRunsMillis" value="50000" />
  		<!-- Configure the minimum lifetime of the connection in milliseconds -->
  		<property name="minEvictableIdleTimeMillis" value="300000" />
	</bean>
	
	<!-- statement sessionFactory  And injection mybatis.config.xml(mybatis Basic Profile)-->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- Injection data source -->
		<property name="dataSource" ref="dataSource"></property>
		<property name="mapperLocations">
			<array>
				<value>classpath:mapper/*Mapper.xml</value>
			</array>
		</property>
		<property name="plugins">
			<array>
				<bean class="com.github.pagehelper.PageInterceptor"></bean>
			</array>
		</property>
	</bean>
	<!-- scanning mapper The interface will sqlSessionFactory Injection into mapper Implementing the association between interfaces and configuration files -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- injection Mapper The package where the interface is located-->
		<property name="basePackage">
			<value>
				com.marco.mapper
			</value>
		</property>
		<!-- injection sqlSessionFactory -->
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	</bean>
</beans>

2)application-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.marco.service.impl"></context:component-scan>
	<!-- 1,Declare Transaction Manager -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- Start annotation transaction -->
	<tx:annotation-driven/>
	<!-- 2,The propagation feature of declarative transactions is notification -->
	<tx:advice id="advice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED"/>
			<tx:method name="insert*" propagation="REQUIRED"/>
			<tx:method name="save*" propagation="REQUIRED"/>
			<tx:method name="edit*" propagation="REQUIRED"/>
			<tx:method name="verify*" propagation="REQUIRED"/>
			<tx:method name="reset*" propagation="REQUIRED"/>
			<tx:method name="delete*" propagation="REQUIRED"/>
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="upload*" propagation="REQUIRED"/>
			<tx:method name="select*" read-only="true"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="query*" read-only="true"/>
			<tx:method name="*" read-only="true"/>
		</tx:attributes>
	</tx:advice>
	<!-- 3 Conduct AOP Weave into -->
	<aop:config>
		<aop:pointcut expression="execution(* com.marco.service.impl.*.*(..))" id="point"/>
		<aop:advisor advice-ref="advice" pointcut-ref="point"/>
	</aop:config>
</beans>

There's nothing to say about the above two configurations. The next configurations should be noticed. They are all configurations related to Shiro integration. The meaning of each tag is indicated on the tag.

3)application-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	
		<!-- Declare credential matcher -->
	<bean id="credentialsMatcher"
		class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
		<!-- Injection algorithm -->
		<property name="hashAlgorithmName" value="md5"></property>
		<!-- Injection hash times -->
		<property name="hashIterations" value="2"></property>
	</bean>

	<!-- statement realm -->
	<bean id="userRealm" class="com.marco.realms.UserRealm">
		<!-- Injection credential matcher -->
		<property name="credentialsMatcher" ref="credentialsMatcher"></property>
	</bean>

	<!-- Create a Security Manager -->
	<bean id="securityManager"
		class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<!-- injection realm -->
		<property name="realm" ref="userRealm"></property>
	</bean>
	

	<!-- Configure the filter chain -->
	<!-- Shiro Of Web Filter id Must and web.xml Inside shiroFilter Of targetBeanName The value is the same. -->
	<bean id="shiroFilter"
		class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- Shiro Core security interface, this property is required -->
		<property name="securityManager" ref="securityManager" />
		<!-- Links when logon is required(Login page address),Non-essential attributes are automatically searched by default Web Project Root Catalogue"/login.jsp"page -->
		<property name="loginUrl" value="/index.jsp" />
		<!-- Connections to jump after successful login(This attribute is not needed in this case because the processing logic after successful login is in UserController Rigid coding) -->
		<!-- <property name="successUrl" value="/success.action"/> -->
		<!-- Connections displayed when a user accesses resources that are not authorized by him -->
		<property name="unauthorizedUrl" value="/unauthorized.jsp" />
		<!-- The definition of the filter chain, which is executed from top to bottom, will generally be/**Put it at the bottom - >.
		<property name="filterChainDefinitions">
			<value>
				<!-- /** = authc All URLs must be authenticated before they can be accessed - >
				/index.jsp*=anon
				/login/toLogin*=anon
				/login/login*=anon
				<!-- If users access user/logout, use Shiro to cancel session - >.
				/login/logout = logout
				<!-- /** = anon All URLs can not be accessed anonymously - >.
				<!-- /** = authc -->
				<!-- /*/* = authc -->
				<!-- /** = authc All url No anonymous access must be placed at the end -->
				/** = authc
			</value>
		</property>
	</bean>
</beans>

The algorithm we chose here is MD5 algorithm, adding salt and hashing twice. Before, we wrote user information to death through shiro.ini file and encrypted Credential credentials in Java program, but this violated Spring's IoC/DI concept, so we chose to configure some of these new objects in xml. In the file, so that the project will be created by Spring and placed in the IoC container after starting, we can go to fetch it directly.
One thing to note here is that because Maven's Web project is built this time, the Security Manager we used is Default Web Security Manager, which is no longer the former Default Security Manager. Be careful not to write it wrong.
Another knowledge point is the filter Chain Definitions filter chain, which is the "sieve" for url screening in the first step, similar to / login/logout is the access path, and the meaning of the following parameters is listed in the form of tables.

Filter name Filter class describe
anon org.apache.shiro.web.filter.authc.AnonymousFilter Anonymous filter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter If you continue, you need to validate the corresponding form, otherwise you can't pass it.
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter Basic http validation filtering, if not, jump to the room login page
logout org.apache.shiro.web.filter.authc.LogoutFilter Log in and exit filter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter No session to create filters
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter Permission filter
port org.apache.shiro.web.filter.authz.PortFilter Port filter, you can set whether it is a specified port, if not jump to the login page
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter http method filter, which can specify such as post can not be accessed, etc.
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter Role filter to determine whether the current user specifies a role
ssl org.apache.shiro.web.filter.authz.SslFilter The request needs to go through ssl, if not jump back to the login page
user org.apache.shiro.web.filter.authc.UserFilter If you visit a known user, such as remembering my function, go through this filter

6)applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	<import resource="classpath:application-dao.xml"/>
	<import resource="classpath:application-service.xml"/>
	<import resource="classpath:application-shiro.xml"/>
</beans>

5)jdbc.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/shiro
username=root
password=password

6)log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

Finally, the configuration of our web.xml is the final one, of course.
7)web.xml
The following configuration about Shiro integration can not be less, one thing to note is that the name of shiroFilter should be consistent with the name of the filter chain in application-shiro.xml!
Because the content we need to filter is a request released through Dispatcher Servelt, we configure it here in filter-mapping.
< servlet-name > spring MVC </servlet-name > On behalf of you, requests after Dispatcher Servelt is released will be monitored by this shiroFilter!

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>shiro_ssm_layui</display-name>
  <!-- shiro Integration Start -->
	<!-- shiro Skipper, DelegatingFilterProxy By proxy mode spring In containers bean and filter Relevance -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<!-- Set up true Representation by servlet Container control filter Life Cycle -->
		<init-param>
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
		<!-- Set up spring container filter Of bean id,If not set, find and filter-name Coincident bean -->
		<init-param>
			<param-name>targetBeanName</param-name>
			<param-value>shiroFilter</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<servlet-name>springmvc</servlet-name>
	</filter-mapping>
  <!-- shiro End of integration -->
  <!-- Filter -->
  <filter>
  	<filter-name>EncodingFilter</filter-name>
 	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
 	<init-param>
 		<param-name>encoding</param-name>
 		<param-value>UTF-8</param-value>
 	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>EncodingFilter</filter-name>
  	<servlet-name>springmvc</servlet-name>
  </filter-mapping>
  <filter>
  	<filter-name>WebStatFilter</filter-name>
  	<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
  	<!-- File Styles for Injection Filtering -->
  	<init-param>
  		<!-- Inject expressions to eliminate unnecessary ones url,such as.js,/jslib/Wait-->
  		<param-name>exclusions</param-name>
  		<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
  	</init-param>
  	<!--  To configure profileEnable Monitorable Individual url Called sql list -->
  	<init-param>
		<param-name>profileEnable</param-name>
		<param-value>true</param-value>
	</init-param>
	<!-- cookie Monitoring Management Configuration -->
	<init-param>
		<param-name>principalCookieName</param-name>
		<param-value>USER_COOKIE</param-value>
	</init-param>
	<!-- Default sessionStatMaxCount It's 1000. -->  
	<init-param>
		<param-name>principalSessionName</param-name>
		<param-value>USER_SESSION</param-value>
	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>WebStatFilter</filter-name>
  	<!-- Filtered servelt yes StatViewServlet -->
  	<servlet-name>StatViewServlet</servlet-name>
  </filter-mapping>
  <!-- Monitor -->
  <listener>
  	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
  <servlet>
  	<servlet-name>springmvc</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:springmvc.xml</param-value>
  	</init-param>
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>springmvc</servlet-name>
  	<url-pattern>*.action</url-pattern>
  </servlet-mapping>
  <servlet>
	<!-- Introduce StatViewServlet,Essentially one servlet-->
	<servlet-name>StatViewServlet</servlet-name>
	<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
	<!-- Setting up accounts -->
	<init-param>
		<param-name>loginUsername</param-name>
		<param-value>root</param-value>
	</init-param>
	<!-- Setting Password -->
	<init-param>
		<param-name>loginPassword</param-name>
		<param-value>password</param-value>
	</init-param>
	<!-- Setting up a White List -->
	<init-param>
		<param-name>allow</param-name>
		<!-- <param-value>192.168.1.1,192.168.2.4</param-value> -->	
		<param-value></param-value>
	</init-param>
	<!-- Set up a blacklist. Note deny Level above allow,cover deny Address counts allow No access. -->
	<init-param>
		<param-name>deny</param-name>
		<param-value></param-value>
	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>StatViewServlet</servlet-name>
  	<url-pattern>/druid/*</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

Modification of Custom UserRealm and Creation of Login Controller

Formula 15: Create LoginController
Because the view resolver InternalResourceViewResolver has been configured in Spring mvc. XML before, you can go back to login directly here, representing the return to the login.jsp page, although it has been mentioned many times before in Spring MVC, here is a little more.

package com.marco.controller;

import javax.servlet.http.HttpSession;

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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.marco.utils.ActiveUser;

@Controller
@RequestMapping("login")
public class LoginController {
	
	@RequestMapping("toLogin")
	public String toLogin() {
		return "login";
	}
	
	@RequestMapping("login")
	public String login(String username, String userpwd, Model model, HttpSession session) {
		//Encapsulation token
		UsernamePasswordToken token = new UsernamePasswordToken(username, userpwd);
		//Getting Subject Body
		Subject subject = SecurityUtils.getSubject();
		// Calling the principal's login method
		try {
			subject.login(token);
			System.out.println("Successful landing");
			ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
			//Store the current user object in session scope
			session.setAttribute("user", activeUser.getUser());
			return "index";
		} catch (IncorrectCredentialsException e) {
			System.err.println("Incorrect password");
			model.addAttribute("error", "Incorrect password");
		} catch (UnknownAccountException e) {
			System.err.println("user name does not exist");
			model.addAttribute("error", "user name does not exist");
		}
		return "login";
	}
}

Form 16: Modify User Realm
Finally, the key step is to modify User Realm, which we have done in Shiro's introductory chapter before, so it won't be so difficult to understand. Realm is essentially an area of security verification, or you can understand it as a junction, it's like a mage. When you pass in data, the data is first brought into the Security Manager castle by Subject, and then into the Realm junction, where everything is confidential. Simple Authentication Info can be regarded as a messenger, an encrypted message that is transmitted, and at the bottom it will be picked up by the Encircler's credentials. The adapter parses and returns the final result.

package com.marco.realms;

import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.util.ByteSource;
import org.apache.shiro.util.SimpleByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.marco.domain.User;
import com.marco.service.PermissionService;
import com.marco.service.RoleService;
import com.marco.service.UserService;
import com.marco.utils.ActiveUser;

public class UserRealm extends AuthorizingRealm{
	@Autowired
	UserService userService;
	@Autowired
	RoleService roleService;
	@Autowired
	PermissionService permissionService;
			
	/**
	 * Processing Authorization
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//Get the current principal identity information (typically username, email or cell phone number, etc.)
		String principal = (String) token.getPrincipal();
		System.out.println("Current principal is " + principal);
		//Get the current credential credential credential information (typically passwords, etc.)
		char[] credentials = (char[]) token.getCredentials();
		String credential = new String(credentials);
		System.out.println("Current credential is " + credential);
		System.out.println("###@#####################################################");
		//Getting Account Information
		String userName = principal.toString();
		User user = userService.queryUserByUserName(userName);
		if(null != user) {
			//Query user roles
			List<String> roles = roleService.queryRolesByUserId(user.getUserid());
			//Query User's Rights
			List<String> permissions = permissionService.queryPermissionByUserId(user.getUserid());
			//Encapsulating activeUser
			ActiveUser activeUser = new ActiveUser();
			activeUser.setRoles(roles);
			activeUser.setUser(user);
			activeUser.setPermissions(permissions);
			//Assemble "salt"
			String salt = user.getUsername() + user.getAddress();
			ByteSource credentialsSalt = new SimpleByteSource(salt.getBytes());
			SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(activeUser, user.getUserpwd(), credentialsSalt, this.getName());
			return authenticationInfo;
		}
		return null;
	}
	
	/**
	 * Processing authentication
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ActiveUser  activeUser = (ActiveUser) principals.getPrimaryPrincipal();
		List<String> permissions = activeUser.getPermissions();//Getting permissions from activeUser
		List<String> roles = activeUser.getRoles();//Getting roles from activeUser
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		if(null != roles && roles.size() > 0) {
			authorizationInfo.addRoles(roles);//Adding user roles
		}
		if(null != permissions && permissions.size() > 0) {
			authorizationInfo.addStringPermissions(permissions);//Adding user privileges
		}
		return authorizationInfo;
	}
}

Creation of Front View Layer

Finally, the backstage framework has been built almost, and then the processing of the front desk, let's simplify here for testing, after careful consideration, or choose to use the "scrap iron section" front page.
Style 17: Create AppListener listeners
My friend who knows my routine should be aware of the purpose of this thing, mainly in order to let the front desk get the access name of our project through the ${context} command.

package com.marco.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppListener implements ServletContextListener{

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		sce.getServletContext().setAttribute("context", sce.getServletContext().getContextPath());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		
	}
}

Style 18: Create View Layer Pages
First of all, we should pay attention to the structure of our View layer. Is it so simple that we want to cry? After all, what we wrote behind the scenes is so lucky and bitter.

The outermost index.jsp is a jump page. There's nothing to say.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<jsp:forward page="login/toLogin.action"></jsp:forward>
</body>
</html>

The second page login.jsp login page, uh... There's nothing to say.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User login</title>
</head>
<body>
<h1 align="center">User login</h1>
	<h5 style="color: red;" align="center">${error}</h5>
	<form action="${context}/login/login.action" method="post">
		<table align="center" width="50%"  border="1" cellpadding="5" cellspacing="5">
			<tr>
				<td align="right">User name:</td>
				<td>
					<input type="text" name="username">
				</td>
			</tr> 
			<tr>
				<td align="right">Password:</td>
				<td>
					<input type="password" name="userpwd">
				</td>
			</tr> 
			<tr>
				<td colspan="2">
					<input type="submit" value="Submission">
				</td>
			</tr> 
		</table>
	</form>
</body>
</html>

Finally, there's a scrap iron version of index homepage. Don't dislike it!

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>System Home Page</title>
</head>
<body>
	System Home Page
	<hr>
	<shiro:hasPermission name="user:query">
		<a href="${context}/user/query.action">Query Users</a>
		<br>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:add">
		<a href="${context}/user/add.action">Adding users</a>
		<br>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:update">
		<a href="${context}/user/update.action">Modify Users</a>
		<br>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:delete">
		<a href="${context}/user/delete.action">delete user</a>
		<br>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:export">
		<a href="${context}/user/export.action">Export users</a>
		<br>
	</shiro:hasPermission>
</body>
</html>

? Did you notice that I added a tag <shiro:hasPermission name="user:export"> to each function, literally translating hasPermission means having XXXX permission, and the content of name means the name of permission, which means that you have this permission (e.g. user:export). I'll use this button for you, if not, bye bye, not for you.

Project testing

Okay, the whole "Dragon-lowering Eighteenth Style" is finished! The one who knocked was tired. Let's test it. Friends who run errors should pay attention to the configuration files, especially the application-shiro.xml integrated by Shiro and SSM, and the configuration of web.xml.

input http://127.0.0.1:8080/marco/index.jsp After entering a very ugly interface, let's try to log in.

My account passwords are marco and 123456. Let's try entering a wrong account first.

Try typing the wrong password

It's no problem to enter the correct password again. Careful friends will find that we lack an export function here.

Yes, I configure marco's role in the database as 1, and 1 corresponds to Super Administrator. Super Administrator has only four functions, which proves that our security strategy is not a problem.


Posterior language

So far, the preliminary part of our project has been completed. What? The project is not finished yet?
That's right. Next is the transformation phase of our project, which is very helpful for us to learn distributed in the later stage. So, we look forward to it.~

Keywords: Shiro Apache xml Spring

Added by polandsprings on Sun, 04 Aug 2019 10:38:23 +0300