SSM如何整合Shiro实现权限登陆案例

精选30+云产品,助力企业轻松上云!>>> hot3.png

1.话不多说,直接引入ssm以及shiro整合依赖

<!--SSM整合-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.10.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
	
    <!--spring-mybatis整合-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
	<!--springmvc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>


    <!--shiro的核心包-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.2</version>
    </dependency>

    <!--shiro整合spring-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.1</version>
    </dependency>

    <!--单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!--sl4j与log4j2的适配-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.12.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-web</artifactId>
        <version>2.12.1</version>
    </dependency>
</dependencies>

2.shiro-config.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">


    <!--自定义realm交给spring ioc 容器管理-->
    <bean name="realm" class="com.wang.crm.shiro.ShiroRealm"/>

    <!--缓存管理器交给spring ioc 容器管理-->
    <bean name="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>

    <!--将安全管理器交给spring ioc 容器管理-->
    <bean name="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--注入自定义realm-->
        <property name="realm" ref="realm"/>
        <!--注入缓存管理器-->
        <property name="cacheManager" ref="cacheManager"/>
    </bean>
    <!-- shiro 的Web过滤器 -->
    <bean name="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--注入安全管理器-->
        <property name="securityManager" ref="securityManager"/>

        <!--如果没有认证将要跳转的登陆地址 -->
        <property name="loginUrl" value="/login"/>
        <!-- 配置安全规则 -->
        <property name="filterChainDefinitions">
            <value>
                <!-- 登录页面不拦截 -->
                /login anon
                <!--静态资源可以直接访问-->
                /static/** anon
                /upload/** anon
                <!-- user表示身份认证通过可以访问 -->
                /** user
            </value>
        </property>

    </bean>
    <!--
        使用SecurityUtils将securityManager设置到运行环境中
        SecurityUtils.setSecurityManager(securityManager);
    -->
    <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>

    <!-- Shiro生命周期处理器-->
    <bean name="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>

3.spring-config.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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--启用注解扫描,扫描含有注解的类-->
    <context:component-scan base-package="com.wang.*.service"/>

    <!--加载属性配置文件-->
    <context:property-placeholder location="classpath:application.properties"/>

    <!--将数据源交给Spring IOC 容器来管理-->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="initialSize" value="${jdbc.initialSize}"/>
    </bean>

    <!--配置Mapper接口的扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--配置mapper接口所在的包-->
        <property name="basePackage" value="com.wang.crm.mapper"/>
        <!--注入会话工厂-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!--SqlSessionFactory 会话工厂交给spring容器管理-->
    <bean name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置Mapper映射文件的位置-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!--配置jdbc的事务管理器-->
    <bean name="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- aop注解生效 -->
    <aop:aspectj-autoproxy/>

    <!--启用事务注解支持-->
    <tx:annotation-driven transaction-manager="txManager"/>

    <!--引入shiro的核心配置-->
    <import resource="classpath:shiro-config.xml"/>
</beans>

4.springmvc-config.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:mvc="http://www.springframework.org/schema/mvc" 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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--开启注解扫描-->
    <context:component-scan base-package="com.wang.*.controller"/>

    <!-- 启用springmvc注解开发功能-->
    <mvc:annotation-driven/>

    <!--不拦截静态资源-->
    <mvc:default-servlet-handler/>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--文件上传解析器-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 限制文件上传总大小,不设置默认没有限制,单位为字节 200*1024*1024即200M -->
        <property name="maxUploadSize" value="209715200"/>

        <!-- 设置每个上传文件的大小上限 1024*1024*2 2M -->
        <property name="maxUploadSizePerFile" value="2019152"/>

        <!-- 处理文件名中文乱码 -->
        <property name="defaultEncoding" value="UTF-8"/>

        <!-- resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
        <property name="resolveLazily" value="true"/>
    </bean>

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login"/>
            <mvc:exclude-mapping path="/static/**"/>
            <mvc:exclude-mapping path="/upload/**"/>
            <bean class="com.wang.crm.interceptor.AuthHandlerInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 开启aop对类代理 -->
    <aop:config proxy-target-class="true"/>

    <!-- 开启shiro注解支持 配置shiro的注解适配器-->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
</beans>

5.application.properties

jdbc.username=root
jdbc.password=123456
jdbc.url=jdbc:mysql://127.0.0.1:3306/shiro_crm?useSSL=false&serverTimezone=Asia/Shanghai
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.initialSize=5

6.ShiroUtil.java

package com.wang.crm.utils;

import com.wang.crm.shiro.ShiroRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;

/**
 * @author 王一宁
 * @date 2020/3/15 12:52
 */
public class ShiroUtil {
    /**
     * 初始化shiro的环境
     */
    static{
        //1.初始化Shiro的安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        //2.设置用户的权限信息到安全管理器
        //Realm realm = new IniRealm("classpath:shiro.ini");

        //2.使用自己定义二relam 操作数据库 查看权限,不看ini了
        Realm realm = new ShiroRealm();
        securityManager.setRealm(realm);

        //3.配置缓存管理器
        CacheManager cacheManager = new MemoryConstrainedCacheManager();
        securityManager.setCacheManager(cacheManager);

        //4.设置到运行环境中
        SecurityUtils.setSecurityManager(securityManager);
    }

    /**
     * 登录认证授权
     * @param username
     * @param password
     */
    public static Subject login(String username,String password){
        //1.创建一个subject实例
        Subject subject = SecurityUtils.getSubject();

        //2.创建一个用户的账号密码Token
        AuthenticationToken token = new UsernamePasswordToken(username,password);

        //3.登录
        subject.login(token);

        return subject;
    }
}

7.ShiroRealm.java

package com.wang.crm.shiro;

import com.wang.crm.mapper.UserMapper;
import com.wang.crm.model.User;
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.springframework.beans.factory.annotation.Autowired;

import javax.xml.ws.Action;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 王一宁
 * @date 2020/3/15 13:12
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    UserMapper userMapper;

    /**
     * 登录认证
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("开始进行用户登录认证...");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //1.获取用户名 密码
        String username = token.getUsername();
        String password = new String(token.getPassword());

        //2.根据用户名密码,去数据库Mysql 查询用户信息
        User user = userMapper.selectByUserNameAndPassword(username);

        //3.对比结果
        if (!user.getUsername().equals(username)){
            throw new UnknownAccountException("用户名不存在!");
        }
        if (!user.getPassword().equals(password)){
            throw new CredentialsException(("密码错误!"));
        }
        if (user.getStatus() == 1){
            throw new DisabledAccountException("账号被禁用了!");
        }
        if (user.getStatus() == 2){
            throw new LockedAccountException("账号被锁定了!");
        }

        System.out.println("认证成功...");

        //4.创建简单信息认证对象,相当与设置到了Session会话中
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(user,token.getCredentials(),getName());
        return info;
    }

    /**
     * 授权资源
     * 将认证通过的用户的角色和权限设置到用户上
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("开始进行授权...");
        //1.简单授权信息对象,包含了角色和权限信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //2.从数据库中获取角色
        User user = (User) principalCollection.getPrimaryPrincipal();
        Set<String> roleNameSet = userMapper.selectUserRoleNameSet(user.getUserId());
        //添加角色和权限列表
        info.addRoles(roleNameSet);

        //3.查询权限
        Set<String> permissionNameSet = userMapper.selectUserPermissionNameSet(user.getUserId());

        //因为一个用户有很多权限,拼接的 ,需要拆分放入shiro
        Set<String> permissions = new HashSet<>();
        for (String name:permissionNameSet){
            for (String permission : name.split(",")){
                permissions.add(permission);
            }
        }
        //添加角色和权限列表
        info.addStringPermissions(permissions);

        System.out.println("授权完成。。。");
        return info;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding路人王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值