zoukankan      html  css  js  c++  java
  • 在Spring + SpringMVC + mybatis架构的项目基础上集成Shiro

    Shiro使用五步走:

     一、pom文件引入shiro依赖

    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-all</artifactId>
      <version>1.2.5</version>
    </dependency>

    二、在Web.xml中配置shiroFilter

    <!--shiro配置-->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     

    三、在Spring配置文件中引入shiro的配置文件spring-shiro.xml

    <!--引入spring-shiro-->
    <import resource="spring-shiro.xml"/>

    spring-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:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <property name="loginUrl" value="login" />
            <property name="successUrl" value="welcome" />
            <property name="unauthorizedUrl" value="/login" />
            <property name="filters">
                <util:map>
                    <entry key="authc" value-ref="formAuthenticationFilter"/>
                </util:map>
            </property>
            <property name="filterChainDefinitions">
                <value>
                    /static/**  = anon
                    /plugins/** = anon
                    /login*     = anon
                    /logout     = logout
                    /**         = authc
                    /**         = user
                </value>
            </property>
    
        </bean>
    
        <!--创建shiro的安全管理器的对象-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="myShiroRealm" />
    
            <!--声明会话管理器属性-->
            <!--<property name="sessionManager" ref="sessionManager"></property>-->
            <!--声明rememberMe-->
            <property name="rememberMeManager" ref="rememberMeManager"></property>
        </bean>
    
        <!-- 项目自定义的Realm -->
        <bean id="myShiroRealm" class="com.blueice.shiro.MyShiroRealm">
            <property name="credentialsMatcher" ref="credentialsMatcher"/>
            <property name="cachingEnabled" value="false"/>
        </bean>
        <!-- 凭证匹配器(加密器) -->
        <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
            <!--<constructor-arg ref="shiroCacheManager" />-->
            <property name="hashAlgorithmName" value="md5" />
            <property name="hashIterations" value="3" />
            <!--storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码-->
            <property name="storedCredentialsHexEncoded" value="true" />
        </bean>
    
        <!-- 基于表单认证的过滤器 -->
        <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"/>
    
        <!-- 这是干啥的?? -->
        <!--<bean id="lifecycleBeanPostProcessor"
              class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>-->
    
        <!--记住我的配置-->
        <!--声明cookie对象-->
        <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
            <constructor-arg value="rememberMe"></constructor-arg>
            <!--只有http的链接才能使用cookie-->
            <property name="httpOnly" value="true"></property>
            <!--cookie的失效时间30天,单位是秒-->
            <property name="maxAge" value="2592000"></property>
        </bean>
        <!--声明记住我的管理器对象-->
        <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
            <property name="cookie" ref="rememberMeCookie"></property>
        </bean>
    
    
    </beans>

    四、继承AuthorizingRealm,自定义授权和认证信息

    package com.blueice.shiro;
    
    import com.blueice.entity.SysUser;
    import com.blueice.services.IndexService;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.crypto.hash.SimpleHash;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    import javax.annotation.Resource;
    import java.text.ParseException;
    import java.util.*;
    
    /**
     * @desctiption 实现自己的JDBC Realm
     * @author shaoz
     * @date 2020-08-17 14:12
     */
    public class MyShiroRealm extends AuthorizingRealm {
    
        @Resource(name = "indexService")
        private IndexService indexService;
    
        /**
         * 获取授权信息
         * @param principals
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String userName = (String)principals.getPrimaryPrincipal();
    
            // 用户权限列表
            Set<String> permsSet = Collections.singleton("test");
    
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            authorizationInfo.setStringPermissions(permsSet);
    
            return authorizationInfo;
        }
    
        /**
         * 获取认证信息
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    
            String username = token.getUsername();
    
            SysUser user = null;
            if (username != null  && !"".equals(username)) {
                user = indexService.selectUserInfoByUsername(username);
            }
    
            if (null == user) {
                // 没找到帐号
                throw new UnknownAccountException();
            }
            if (user.getStatus() == 0) {
                // 用户被停用
                throw new LockedAccountException();
            }
    
            ByteSource salt = ByteSource.Util.bytes(user.getUsername());
    
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), user.getPassword(),
                     salt, getName());
            return info;
        }
    
    
        public static void main(String[] args) throws ParseException {
            String hashAlgorithmName = "MD5";
            String credentials = "123456";
            int hashIterations = 3;
            ByteSource salt = ByteSource.Util.bytes("test");
            Object obj = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
            System.out.println(obj);
    
        }
    }

    五、在controller层实现登录认证&退出登录

    @RequestMapping(value="/login_login")
    @ResponseBody
    public String login_login(String username, String password, String isRememberMe) {
    
        String error = null;
        try {
            username = URLDecoder.decode(username, "UTF-8");
            password = URLDecoder.decode(password, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(username + password);
        // 先把账号密码传入shiro里面的UsernamePasswordToken对象里面
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 创建Subject对象
        Subject subject = SecurityUtils.getSubject();
    
        if ("1".equals(isRememberMe)) {
            token.setRememberMe(true);
        }
    
        // 调用subject.login()进行登录
        try {
            subject.login(token);
    
            //SysUser sysUser = (SysUser) subject.getPrincipals();
        } catch (UnknownAccountException e) {
            error = "用户名/密码错误";
        } catch (IncorrectCredentialsException e) {
            error = "用户名/密码错误";
        } catch (ExcessiveAttemptsException e) {
            // TODO: handle exception
            error = "登录失败多次,账户锁定10分钟";
        } catch (AuthenticationException e) {
            // 其他错误,比如锁定,如果想单独处理请单独catch处理
            error = "其他错误:" + e.getMessage();
        }
    
        if (error != null) {
            // 出错了,返回登录页面
    
            return error;
        } else {
            // 登录成功
            return "success";
        }
        
        /**
         * 退出登录
         * @return
         */
        @RequestMapping("/logout")
        public ModelAndView logout() {
            ModelAndView mv = new ModelAndView();
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
            mv.setViewName("login");
            return mv;
        }
    }

    shiro使用就是这么简单,原理:下次搞懂了再讲。。。

  • 相关阅读:
    Hsqldb中设置主键,并让主键自增
    解决Hsqldb指针只能单向移动,不能回滚问题(.first())
    MySql服务的启动和停止
    jetty和tomcat比较
    查看某一端口被什么程序占用
    小程序修改swiper小圆点
    小程序返回上一页。或者某一页上刷新返回页
    小程序或者vue商品秒杀倒计时
    小程序 wx.switchTab 不能带参数的解决办法
    微信小程序倒计时60S
  • 原文地址:https://www.cnblogs.com/steveshao/p/13555169.html
Copyright © 2011-2022 走看看