shiro+spring+ehCache+maven整合开发 案例框架使用的shiro 整合使用的spring 缓存技术使用的ehcache 项目搭建使用的maven 1.导包- <!-- 权限控制 框架 -->
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-all</artifactId>
- <version>1.2.2</version>
- </dependency>
- <!-- spring 框架 -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-orm</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jms</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aspects</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <!-- spring data jpa 数据库持久层 -->
- <dependency>
- <groupId>org.springframework.data</groupId>
- <artifactId>spring-data-jpa</artifactId>
- <version>${springdatajpa.version}</version>
- </dependency>
- <!-- 缓存 -->
- <dependency>
- <groupId>net.sf.ehcache</groupId>
- <artifactId>ehcache-core</artifactId>
- <version>2.6.11</version>
- </dependency>
2.shiro开发先进行shiro和spring整合实现登录和权限管理 2.1 在web.xml配置shiro的过滤器- <!-- shiro的Filter -->
- <filter>
- <!-- 去spring配置文件中寻找同名bean -->
- <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>
注意: web.xml中的配置文件是有顺序的。shiro的过滤器要放在别的过滤器前面 2.2 添加spring配置文件- <!-- 配置Shiro核心Filter -->
- <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.html" />
- <!-- 认证后,没有权限跳转页面 -->
- <property name="unauthorizedUrl" value="/unauthorized.html" />
- <!-- shiro URL控制过滤器规则 -->
- <property name="filterChainDefinitions">
- <value>
- /login.html* = anon //放行
- /user_login.action* = anon
- /validatecode.jsp* = anon
- /css/** = anon
- /js/** = anon
- /images/** = anon
- /services/** = anon
- /pages/base/courier.html* = perms[courier:list] //权限
- /pages/base/area.html* = roles[base] //角色
- /** = authc
- <--anon 未认证可以访问
- authc 认证后可以访问
- perms 需要特定权限才能访问
- roles 需要特定角色才能访问
- user 需要特定用户才能访问
- port 需要特定端口才能访问
- reset 根据指定 HTTP 请求访问才能访问 -->
- </value>
- </property>
- </bean>
- <!-- 安全管理器 -->
- <bean id="securityManager"
- class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- //自定义的Realm
- <property name="realm" ref="bosRealm" />
- //自己定义的缓存 如果没有使用缓存要删除掉
- <property name="cacheManager" ref="shiroCacheManager" />
- </bean>
- <!-- 配置Realm -->
- <bean id="bosRealm" class="cn.tpr.bos.realm.BosRealm">
- <!-- 缓存区的名字 就是 ehcache.xml 自定义 cache的name -->
- //自己定义的缓存 如果没有使用缓存要删除掉
- <property name="authorizationCacheName" value="bos" />
- </bean>
- <!-- 开启shiro注解模式 -->
- <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>
2.3更改spring代理方式默认使用的是jdb动态代理,无法获取shiro的注解 改成cglib代理 - <!-- 注解管理事务 -->
- <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
2.3 编写登录方法- @Action(value = "user_login", results = {
- @Result(name = "login", type = "redirect", location = "login.html"),
- @Result(name = "success", type = "redirect", location = "index.html") })
- public String login() {
- // 用户名和密码 都保存在model中
- // 基于shiro实现登录
- Subject subject = SecurityUtils.getSubject();
- // 用户名和密码信息
- AuthenticationToken token = new UsernamePasswordToken(
- model.getUsername(), model.getPassword());
- try {
- //此处调用了自定义Realm
- subject.login(token);
- // 登录成功
- // 将用户信息 保存到 Session
- return SUCCESS;
- } catch (AuthenticationException e) {
- // 登录失败
- e.printStackTrace();
- return LOGIN;
- }
- }
2.4编写自定义RealmRealm使用的是配置bean的方式配置的。要和上面配置文件中的Realm中的class的权限定名一制 此处 cn.tpr.bos.realm.BosRealm 代码 如下: - // @Service("bosRealm")
- public class BosRealm extends AuthorizingRealm {
- @Autowired
- private UserService userService;
- @Autowired
- private RoleService roleService;
- @Autowired
- private PermissionService permissionService;
- @Override
- // 授权...
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
- System.out.println("shiro 授权管理...");
- SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
- // 根据当前登录用户 查询对应角色和权限
- Subject subject = SecurityUtils.getSubject();
- User user = (User) subject.getPrincipal();
- // 调用业务层,查询角色
- List<Role> roles = roleService.findByUser(user);
- for (Role role : roles) {
- authorizationInfo.addRole(role.getKeyword());
- }
- // 调用业务层,查询权限
- List<Permission> permissions = permissionService.findByUser(user);
- for (Permission permission : permissions) {
- authorizationInfo.addStringPermission(permission.getKeyword());
- }
- return authorizationInfo;
- }
- @Override
- // 认证...
- protected AuthenticationInfo doGetAuthenticationInfo(
- AuthenticationToken token) throws AuthenticationException {
- System.out.println("shiro 认证管理... ");
- // 转换token
- UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
- // 根据用户名 查询 用户信息
- User user = userService.findByUsername(usernamePasswordToken
- .getUsername());
- if (user == null) {
- // 用户名不存在
- // 参数一: 期望登录后,保存在Subject中信息
- // 参数二: 如果返回为null 说明用户不存在,报用户名
- // 参数三 :realm名称
- return null;
- } else {
- // 用户名存在
- // 当返回用户密码时,securityManager安全管理器,自动比较返回密码和用户输入密码是否一致
- // 如果密码一致 登录成功, 如果密码不一致 报密码错误异常
- return new SimpleAuthenticationInfo(user, user.getPassword(),
- getName());
- }
- }
- }
springt和shiro小结到此shiro和spring整合完成。密码不正确或者账号为空都会抛出不同的异常,只要捕获后处理就好了。 权限 控制 有最少五张表 用户、 角色、 权限还有两张是角色和他们之间的关联表 三、shiro使用ehcache缓存3.1 添加ehcache缓存配置文件- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
- <diskStore path="java.io.tmpdir"/>
- <defaultCache
- maxElementsInMemory="10000"
- eternal="false"
- timeToIdleSeconds="120"
- timeToLiveSeconds="120"
- maxElementsOnDisk="10000000"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU">
- <persistence strategy="localTempSwap"/>
- </defaultCache>
- <cache name="bos"
- maxElementsInMemory="10000"
- eternal="false"
- timeToIdleSeconds="120"
- timeToLiveSeconds="120"
- maxElementsOnDisk="10000000"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU">
- <persistence strategy="localTempSwap"/>
- </cache>
- 、//为一个缓存单位
- <cache name="standard"
- maxElementsInMemory="10000"
- eternal="false"
- timeToIdleSeconds="120"
- timeToLiveSeconds="120"
- maxElementsOnDisk="10000000"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU">
- <persistence strategy="localTempSwap"/>
- </cache>
- </ehcache>
3.2配置缓存管理器- <!-- 缓存配置 -->
- <bean id="ehCacheManager"
- class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation" value="classpath:ehcache.xml" />
- </bean>
3.3shiro封装cacheManager缓存管理器- <!-- shiro封装cacheManager -->
- <bean id="shiroCacheManager"
- class="org.apache.shiro.cache.ehcache.EhCacheManager">
- <property name="cacheManager" ref="ehCacheManager" />
- </bean>
3.4shiro使用缓存管理器在上面配置Realm的时候添加一个property对象 下面就是授权缓存 一个用户只要授权一次就可以了,不会在多请求Realm - <!-- 配置Realm -->
- <bean id="bosRealm" class="cn.tpr.realm.BosRealm">
- <!-- 缓存区的名字 就是 ehcache.xml 自定义 cache的name -->
- //自己定义的缓存 如果没有使用缓存要删除掉
- <property name="authorizationCacheName" value="bos" />
- </bean>
spring+ehcache缓存普通数据在接着上面的对ehcache的配置后面继续添加配置,来缓存普通数据 1和spring整合 让spring来管理缓存- <!-- spring 封装ehcache缓存管理器 -->
- <bean id="springCacheManager"
- class="org.springframework.cache.ehcache.EhCacheCacheManager">
- <property name="cacheManager" ref="ehCacheManager" />
- </bean>
2.激活spring缓存注解- <!-- 激活spring 缓存注解 -->
- <cache:annotation-driven cache-manager="springCacheManager"/>
3配置文件中的名称 空间4.需要操作的pojo类实现序列化接口- public class Menu implements Serializable {
5.在service层实现方法中添加标签5.1 添加缓存- @Cacheable("standard") 这个标签指把查询出来 的数据添加standard 这个缓存空间中是在ehcache中配置的
- @Override
- @Cacheable("standard")
- public List<Standard> findAll() {
- return standardRepository.findAll();
- }
5.2修改缓存- @CacheEvict(value = "standard", allEntries = true)
- 修改缓存空间中的值
- @Override
- @CacheEvict(value = "standard", allEntries = true)
- public void save(Standard standard) {
- standardRepository.save(standard);
- }
5.3分页缓存- @Override
- @Cacheable(value = "standard", key = "#pageable.pageNumber+'_'+#pageable.pageSize")
- public Page<Standard> findPageData(Pageable pageable) {
- return standardRepository.findAll(pageable);
- }
|