Shiro erection

Use the ssm framework, xml and annotations to build the shiro framework. Beginners only build the simplest framework and provide basic usage such as authentication, authorization, and password management.

1. To build an ssm project, there is no need to connect to the database. The code is hard-coded here, and you can access it normally. Build shiro on the basis of this project

Two, import shiro dependencies

<!-- shiro 依赖 -->
        <dependency>
        	<groupId>org.apache.shiro</groupId>
        	<artifactId>shiro-all</artifactId>
        	<version>1.2.3</version>
        </dependency>

Three, add shiro filtering in web.xml

 <!-- shiro安全过滤器 filter-name这个名字的值会在spring的配置中被引用 -->
	  <filter>
	  		<filter-name>shiroFilter</filter-name>
	  		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	  		<init-param>
	  			<param-name>targetFilterLifecycle</param-name>
	  			<param-value>true</param-value>
	  		</init-param>
	  </filter>
	  <filter-mapping>
	  		<filter-name>shiroFilter</filter-name>
	  		<url-pattern>/*</url-pattern>
	  </filter-mapping>

Fourth, write a spring configuration file, according to this configuration file, perfect the construction of shiro

<?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:p="http://www.springframework.org/schema/p"  
	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/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    
	http://www.springframework.org/schema/context    
	http://www.springframework.org/schema/context/spring-context.xsd">
	
	<description>Shiro的配置</description>
	
	<!-- 自定义权限认证:类1,shiro的核心类,这个类需要注入两个属性
         属性1:loginService,这是用于登录的服务的具体实现类,由我们自身业务提供;
         属性2:credentialsMatcher,这个属性不可变,具体的引用类由我们自己写,
                写的这个引用类需要继承SimpleCredentialsMatcher这个类,并且实现
                doCredentialsMatch()这个方法
    -->
	<bean id="authRealm" class="com.enjoy.shiro.AuthRealm">
        <!--登录服务:类2--><!--注解注入-->
		<!--<property name="loginService" ref="loginService"></property>-->
		<!-- 自定义的类,需继承其他类,将这个类通过注解方式注入到spring中,在这里被引用 :类3-->
		<property name="credentialsMatcher" ref="passwordMatcher"/>
	</bean>

	<!-- SecurityManager配置,安全管理配置,引用自定义的authRealm -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="realm" ref="authRealm"/><!-- 引用自定义的realm -->
    </bean>
   
    <!-- filter-name这个名字的值来自于web.xml中filter的名字,shiro核心控制器,默认加载其他过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录页面  -->
        <property name="loginUrl" value="/index"></property>
        <!-- 登录成功后 -->      
        <property name="successUrl" value="/index2"></property>
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤 -->
            <value>
				/login = anon
				/logout = anon
				/css/** = anon
				/images/** = anon
				/js/** = anon
				/skin/** = anon
				/resource/** = anon
				/** = authc
				/*.* = authc
            </value>
        </property>
    </bean>
<!--下面这三个类是固定写法,不需要修改-->
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 生成代理,通过代理进行控制 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true"/>
    </bean>
    
    <!-- 安全管理器 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
	
</beans>

5. According to the configuration file of the fourth part, write our custom class, there are three classes that we need to implement

(1) Login service class-loginService, this class can be written according to your actual business, I did not check the database here, and the user name is hard to write. As long as the user name is entered, the user can be queried and the user's detailed information can be obtained .

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.enjoy.domain.User;

@Service
public class LoginService {
	
	@Autowired
	private User user;
	
	public int login(String username,String password) {
		if("zh".equals(username)) {
			return 1;
		}
		return 0;
	}
	
	public User getUser() {
		return user;
	}

}

(2) Custom authority authentication class—AuthRealm, inherit the AuthorizingRealm class, and override the authentication and authorization method

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.authc.UsernamePasswordToken;
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.springframework.beans.factory.annotation.Autowired;

import com.enjoy.domain.User;
import com.enjoy.service.LoginService;

public class AuthRealm extends AuthorizingRealm{
	
	@Autowired
	private LoginService loginService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
		System.out.println("调用授权方法");
		
		//获取当前用户,拿到用户详细信息
		User user = (User)pc.getPrimaryPrincipal();
		
		//获取授权类,添加授权信息
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addStringPermission("系统首页");
		info.addStringPermission("系统");
		
		return info;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("调用认证方法");
		//获取token,得到用户名和密码
		UsernamePasswordToken token = (UsernamePasswordToken)arg0;
		String username = token.getUsername();
		String password = new String(token.getPassword());
		int i = loginService.login(username, password);
		//如果用户存在,则返回info,走密码对比,否则返回null,抛出异常
		if(i ==1) {
			User user = loginService.getUser();
			SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
			return info;                        
		}else {
			return null;
		}
	}
}

(3) The custom password comparison algorithm class—CustomCredentialsMatcher, needs to inherit the SimpleCredentialsMatcher class and override the doCredentialsMatch method

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.springframework.stereotype.Component;

/**
 * 
 * @author myPC
 *     自定义加密算法
 */
@Component(value="passwordMatcher")
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher{

	@Override
	/*
	 * 参数1:token,用户输入信息
	 * 参数2:info,数据库查出的信息
	 * 返回值:布尔值
	 */
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		//比较用户输入的密码和数据库密码是否一致
		System.out.println("调用自定义密码对比方法");
		//获取用户输入的密码
		char[] password = ((UsernamePasswordToken)token).getPassword();
		String pw = new String(password);
		String md5 = MD5Util.getMD5(pw, ((UsernamePasswordToken)token).getUsername(), 2);
		//获取数据库存的密码
		Object obj = info.getCredentials();
		return equals(md5,obj);
	}

}

Some of the above three classes are injected into spring through xml, and some are injected through annotations. Need to be clear.

With MD5 encryption tools

import org.apache.shiro.crypto.hash.Md5Hash;

public class MD5Util {
	
	public static String getMD5(String arg0,String arg1,int arg2) {
		//MD5加密
		//参数1:要加密的字符串,参数2:混淆的字符串,参数3,哈希几次
		Md5Hash hash = new Md5Hash(arg0,arg1,arg2);
		
		return hash.toString();
		
	}

}

Six, call shiro method to enter entry login

 

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/")
public class IndexController {
	
	@RequestMapping("login")
	public String toLogin(String username,String password) {
		
		//获得subject
		Subject subject = SecurityUtils.getSubject();
		//创建令牌,传入用户名和密码
		UsernamePasswordToken token = new UsernamePasswordToken(username,password); 
		try {
        //调用subject的login方法,传入令牌,如果没跑出异常,则进入index2方法,否则进入login
			subject.login(token);
		} catch (Exception e) {
			System.out.println("未验证,请登录");
			return "login";
		}
		return "index2";
	}

Seven, start the project, enter licalhost:8090/login

Enter the user name and password, zh/123

     

According to the corresponding page on the right, the name value of the system homepage is authorized and the label is displayed, and the name value of the system 1 is not authorized, and it is not displayed

@RequiresPermissions({"系统首页"})
	@RequestMapping("index4")
	public String toIndex4() {
		return "index4";
	}

The index4 path needs to be authorized by the system homepage to access it.

8. Summary. The entire access process is intercepted by web.xml. In the spring configuration, multi-level directory filtering is used for authorization. When the system is accessed, the subject.login() method is called, the authentication method is used, and the password is compared if it is correctly released. Authorization is required for access, and then the authorization method is used to determine whether there is authorization, and let it if there is authorization.

 

 

Guess you like

Origin blog.csdn.net/csdnbeyoung/article/details/95869492