Shiro与SpringMVC整合的基本配置与案例(IDEA工具)

基于Shiro的用户认证

1.创建web工程

Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
由于IDEA的web工程不会创建java和resouces目录,所以需要手动创建
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)

2.在pom.xml导入相关坐标

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>shiro_spring_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
    </dependencies>
</project>

3.修改WEB-INF下的web.xml配置文件

<?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_2_5.xsd"
         version="2.5">
    <!--spring核心监听器,默认加载WEB-INF目录下的applicationContext.xml-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/applicationContext*.xml</param-value>
    </context-param>
    <!--springMVC-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    <!--配置 spring 中提供的 shiro 过滤器(一当十的过滤器)-->
    <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>
</web-app>

4.在resouces下增加目录spring下增加配置文件springmvc.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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--    扫描注解-->
    <context:component-scan base-package="com.demo"/>
    <!--    注解驱动-->
    <mvc:annotation-driven/>
</beans>

5.在spring下增加shiro的核心配置文件applicationContext-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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置Spring整合shiro -->
    <!-- 配置安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 自己编写一个realm域对象 -->
        <property name="realm" ref="authRealm"/>
    </bean>

    <!-- 编写realm类 -->
    <bean id="authRealm" class="com.demo.shiro.AuthRealm">
        <!-- 注入密码比较器对象 -->
        <property name="credentialsMatcher" ref="customCredentialsMatcher"/>
    </bean>

    <!-- 密码比较器类 -->
    <bean id="customCredentialsMatcher" class="com.demo.shiro.CustomCredentialsMatcher"/>

    <!-- Spring框架需要整合shiro安全框架 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 注入安全管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 登录页面 -->
        <property name="loginUrl" value="/login.html"/>
        <!-- 认证成功了,跳转的页面-->
        <property name="successUrl" value="/index.jsp"/>
        <!-- 没有权限的跳转页面 -->
        <property name="unauthorizedUrl" value="/error.html"/>
        <!-- 定义访问的规则 -->
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤 -->
            <value>
                /login.do=anon
                /login.html = anon
                /error.html = 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>

6.最终工程目录

Shiro与SpringMVC整合的基本配置与案例(IDEA工具)

7.添加相关代码

UserController.java
package com.demo.controller;

import com.demo.domain.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    //登录
    @RequestMapping("/login")
    public String login(String username, String password) {
        try {
            //1.得到subject对象
            Subject subject = SecurityUtils.getSubject();
            //2.封装用户数据
            AuthenticationToken token = new UsernamePasswordToken(username, password);
            //3.实现登录操作
            subject.login(token);
            //4.登录成功后,可以从shiro取出用户信息
            User user = (User) subject.getPrincipal();
            return "redirect:/index.jsp";
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return "redirect:/error.html";
        }
    }

    //退出
    @RequestMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/login.html";
    }
}
User.java
package com.demo.domain;

public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    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;
    }
}

自定义认证域 AuthRealm.java
package com.demo.shiro;

import com.demo.domain.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

//自定义realm域
public class AuthRealm extends AuthorizingRealm {

    //授权:赋予用户角色
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //认证:验证登录时用户输入的账号和密码
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //强转拿到存有用户输入的账号密码的对象
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        //获取账号
        String username = upToken.getUsername();
        //模拟安全认证对象(一般根据username去数据库查,这里只做模拟)
//        User user = userService.findUserByUsername(username);
        User user = null;
        if ("admin".equalsIgnoreCase(username)) {
            user = new User("admin", "admin");
        }
        //判断对象在数据库中是否存在
        if (user != null) {
            //第一个参数:安全数据(user对象)
            //第二个参数:密码(数据库密码)
            //第三个参数:当前调用realm域的名称(类名即可)
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
            return info;
        }
        return null;
    }
}

自定义密码比较器 CustomCredentialsMatcher.java
package com.demo.shiro;

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;

//自定义密码比较器
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
    /**
     * @param token 用户界面输入的账号和密码
     * @param info  安全数据:用户对象user
     * @return
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //向下强转获得实现类
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        //获取用户输入的密码
        String inputPwd = new String(upToken.getPassword());
        //获取认证类传入的安全认证对象密码
        String dbPwd = info.getCredentials().toString();
        //返回判断密码结果
        return dbPwd.equals(inputPwd);
    }
}

8.添加登录页面login.html和失败error.html

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/login.do" method="post">
    <table align="center">
        <tr>
            <td>账号:</td>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input style="width: 100%" type="submit" value="登录">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆失败</title>
</head>
<body>
<h1>账号或密码错误!</h1>
<a href="/login.html"><h3>回到登录页</h3></a>
</body>
</html>

9.启动服务和测试

配置tomcat可以参考我的配置tomcat博客,这里就不再赘述了,

启动之后弹出页面:
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
第一次测试,输入正确账号admin,密码admin
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
第二次测试,输入错误账号admin111,密码admin111
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
点击登录之后
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
第三次测试,输入正确账号admin,错误密码admin111
Shiro与SpringMVC整合的基本配置与案例(IDEA工具)
至此,配置shiro和springmvc整合完成了,如果遇到问题可以私我,也可以发表评论。
谢谢观看,如有不足,还请指正。