跟我学Shiro实践-整合Spring

仅作为个人代码翻阅记录

maven依赖

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- 日志SLF4j 接口 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <!--实现slf4j接口并整合 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- Shiro安全框架 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- 数据源dataSource -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
        <!-- Spring 集成shiro -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- Shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!-- Shiro注解 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!-- Redis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

        <!-- jsp依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>shiro</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <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>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/spring-*.xml</param-value>
  </context-param>
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

 login.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录界面</title>
    </head>
    <body>
        <form action="subLogin" method="post">
            用户名:<input type="text" name="username"><br>
            密    码:<input type="password" name="password"><br>
            记住我:<input type="checkbox" name="rememberMe"><br>
            <input type="submit" value="登录"> 
        </form>
    </body>
</html>

UserController

@Controller
public class UserController {
    
    @RequestMapping(
            value="/subLogin", 
            method=RequestMethod.POST,
            produces="application/json;charset=utf-8")
    @ResponseBody
    public String subLogin(User user) {
        
        Subject subject = SecurityUtils.getSubject();
        
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        
        try {
            token.setRememberMe(user.isRememberMe());
            subject.login(token);
        } catch (Exception e) {
            return e.getMessage();
        }
        
        // 编码方式判断是否具有管理员身份
        if (subject.hasRole("admin")) {
            return "有admin权限";
        }
        
        return "无admin权限";
    }
    
    //通过注解设置角色权限为admin才可访问
    @RequiresRoles("admin")    
    @RequestMapping(value="/testRole", method=RequestMethod.GET)
    @ResponseBody
    public String testRole() {
        return "test role success";
    }
    
    /**
     * 通过在service.xml配置访问权限
     */
    @RequestMapping(value="/testRoles", method=RequestMethod.GET)
    @ResponseBody
    public String testRoles() {
        return "test roles success";
    }
    
    @RequestMapping(value="/testRoles1", method=RequestMethod.GET)
    @ResponseBody
    public String testRoles1() {
        return "test roles1 success";
    }
    
    @RequestMapping(value="/testPerms", method=RequestMethod.GET)
    @ResponseBody
    public String testPerms() {
        return "test roles success";
    }
    
    @RequestMapping(value="/testPerms1", method=RequestMethod.GET)
    @ResponseBody
    public String testPerms1() {
        return "test roles1 success";
    }
    
}

 spring.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-4.2.xsd">

    <import resource="spring-dao.xml" />
    
    <context:component-scan base-package="net.laoyeye.controller" />

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>
        <property name="loginUrl" value="login.html"></property>
        <property name="unauthorizedUrl" value="403.html"></property>
        <property name="filterChainDefinitions">
            <value>
                /login.html = anon
                /test = anon
                /test.do = anon
                /testRoles = roles["admin","admin1"]
                /testRoles1 = rolesOr["admin","admin1"]
                /subLogin = anon
                /* = authc
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="rolesOr" value-ref="rolesOrFilter" />
            </map>
        </property>
    </bean>
    
    <!-- 自定义filter -->
    <bean id="rolesOrFilter" class="net.laoyeye.filter.RolesOrFilter" />
    
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="realm"></property>
    </bean>
    
    <bean id="realm" class="net.laoyeye.realm.CustomRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher" ></property>
    </bean>
    
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="md5" />
        <property name="hashIterations" value="1" />
    </bean>

</beans>

 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: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-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">

    <context:component-scan
        base-package="net.laoyeye.controller"></context:component-scan>

    <mvc:annotation-driven />
    <!-- 排除静态文件 -->
    <mvc:resources location="/" mapping="/*" />
    
    <!-- 开启AOP -->
    <aop:config proxy-target-class="true" />

    <!-- 保证 Shiro内部生命周期 -->
    <bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>

    <!-- 开启Shiro授权生效 -->
    <bean
        class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>

</beans>

  自定义Filter实现

/**
 * 自定义权限过滤器
 * 也可以自定义其他过滤器
 * @author Administrator
 *
 */
public class RolesOrFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest req,
            ServletResponse resp, Object object) throws Exception {
        
        Subject subject = getSubject(req, resp);
        
        String[] roles = (String[]) object;
        
        if (roles == null || roles.length == 0) {
            return true;
        }
        
        for (String role : roles) {
            if (subject.hasRole(role)) {
                return true;
            }
        }
        
        return false;
    }

}

 自定义sessionManage

import java.io.Serializable;

import javax.servlet.ServletRequest;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;

/**
 * Create by laoyeye
**/
public class CustomSessionManage extends DefaultWebSessionManager {

    @Override
    protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
        Serializable sessionId = getSessionId(sessionKey);
        ServletRequest request = null;
        if(sessionKey instanceof WebSessionKey) {
            request = ((WebSessionKey)sessionKey).getServletRequest();
        }
        if(request != null && sessionId != null) {
            Session session =  (Session) request.getAttribute(sessionId.toString());
            if(session != null) {
                return session;
            }
        }    
        Session session = super.retrieveSession(sessionKey);
        if(request != null && sessionId != null) {
            request.setAttribute(sessionId.toString(), session);
        }
        return session;
    }

}

自定义cacheManage

public class RedisCacheManager implements CacheManager {
    
    @Resource
    private RedisCache redisCache;

    @Override
    public <K, V> Cache<K, V> getCache(String s) throws CacheException {

        return redisCache;
    }

}

 重写后的spring.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"
    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-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
        
    <bean id="shiroFilter"
        class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>
        <property name="loginUrl" value="login.html"></property><!-- 没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面 -->
        <property name="unauthorizedUrl" value="403.html"></property><!-- 没有权限默认跳转的页面 -->
        <property name="filterChainDefinitions">
            <value><!-- 自上到下 --><!-- anon:表示可以匿名使用。 authc:表示需要认证(登录)才能使用,没有参数.  roles["admin,guest"],每个参数通过才算通过,user表示必须存在用户 -->
                /login.html = anon
                /subLogin = anon
                /testRoles = roles["admin"]
                /testRoles1 = rolesOr["admin","admin1"]
                /testPerms = perms["user:delete"]
                /testPerms1 = perms["user:delete","user:updata"]
                /* = authc
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="rolesOr" value-ref="rolesOrFilter" />
            </map>
        </property>
    </bean>
    
    <!-- 自定义权限filter -->
    <bean id="rolesOrFilter" class="net.laoyeye.filter.RolesOrFilter" />
    
    <!-- 创建SecurityManager对象 -->
    <bean id="securityManager"
        class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="realm" />
        <property name="sessionManager" ref="sessionManager" />
        <property name="cacheManager" ref="cacheManager" />
        <property name="rememberMeManager" ref="cookieRememberMeManager" />
    </bean>

    <!-- 自定义Realm -->
    <bean id="realm" class="net.laoyeye.realm.CustomRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher" ></property>
    </bean>
    
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="md5" />
        <property name="hashIterations" value="1" />
    </bean>
    <!-- 自定义SessionManager -->
    <bean class="net.laoyeye.session.CustomSessionManage" id="sessionManager">
        <property name="sessionDAO" ref="redisSessionDao"></property>
    </bean>

    <bean class="net.laoyeye.session.RedisSessionDao" id="redisSessionDao"></bean>
    
    <bean class="net.laoyeye.cache.RedisCacheManager" id="cacheManager"></bean>
    
    <!-- 自动登录 -->
    <bean class="org.apache.shiro.web.mgt.CookieRememberMeManager" id="cookieRememberMeManager">
        <property name="cookie" ref="cookie"></property>
    </bean>
    
    <bean class="org.apache.shiro.web.servlet.SimpleCookie" id="cookie">
        <constructor-arg name="name" value="rememberMe" />
        <property name="maxAge" value="20000000" />
    </bean>
    
</beans>

 

posted @ 2018-06-18 14:32  小卖铺的老爷爷  阅读(308)  评论(0)    收藏  举报


^
TOP