`
孙宁振
  • 浏览: 34898 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类

spring security 2.0 的简单配置使用

阅读更多

 由于ss2的demo配置太过简单,要想在项目中应用的话必须进行相应扩展,这里简单写一下简单的扩展方法。

xml头中引入security命名空间

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           	http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"
    default-lazy-init="true">

 

 然后是启用ss2默认配置的一段代码

    <!--
        2.0新增的命名空间,使得配置简化了很多
        auto-config 自动使用默认的配置
        access-denied-page 指定访问未授权页面时显示的页面
    -->
    <security:http auto-config="true" access-denied-page="/accessDenied.html">
        <security:anonymous granted-authority="BASIC" />
    </security:http>

  这段代码作用是以ss2的默认配置方式加入1.0时需要手工配置的AuthenticationProcessingFilter等多个必须配置的filter,详细可参考1.0配置和2.0参考手册。

auto-config="true" 表示使用ss2自动配置

access-denied-page="/accessDenied.html"表示拒绝访问时显示的页面

<security:anonymous granted-authority="BASIC" />表示匿名权限的authority为BASIC

 

ss对权限的管理分为认证和授权两部分,先看认证

    <!-- 
        负责认证处理的filter
    -->
    <bean id="authenticationProcessingFilter"
        class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
        <!-- 此行说明此filter会覆盖ss2默认配置的filter,before 被覆盖filter的别名 -->
        <security:custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
        <!-- 认证管理器 -->
        <property name="authenticationManager" ref="authenticationManager" />
        <!-- 认证失败后跳转到的页面,/spring_security_login是ss2默认的登录入口 -->
        <property name="authenticationFailureUrl"
            value="/spring_security_login" />
        <!-- 认证成功后跳转到的页面 -->
        <property name="defaultTargetUrl" value="/index.html" />
    </bean>

 这是负责认证处理的filter,中间custom-filter一行意思是将filter放在默认配置中别名为AUTHENTICATION_PROCESSING_FILTER的filter前边,即负责认证的filter(别名列表参照参考手册)。

按官方的说法,如果需要用自定义的filter覆盖默认filter,则应该将security:http标签的auto-config属性改为false,这样的话就需要增加很多手动配置项。我试了下,不改false也可以,只是运行期间会出现一个warn信息“Possible error: Filters at position 2 and 3 are both instances of xxxx”,意思是filter串中有两个相同类型的filter。

另:在2.0.2中可以使用position代替before,真正的覆盖默认filter。但是有个bug,如果使用默认登录入口的话,还是会调用默认filter,必须连登录入口一并改掉。

 

其引用的authenticationManager

    <!--
        认证管理器
        根据用户名和密码,使用多个provider进行认证
        认证成功会生成一个Authentication,否则抛出AuthenticationException
    -->
    <bean id="authenticationManager"
        class="org.springframework.security.providers.ProviderManager">
        <property name="providers">
            <list>
                <ref local="daoAuthenticationProvider" />
            </list>
        </property>
    </bean>

 认证管理器通过多个provider实现基于用户名和密码的认证,多个provider中只要有一个认证成功,即成功。

 

这里只使用了一个daoPorvider

    <!--
        认证的provider
        userDetailsService 根据用户名获取用户信息
        userCache ehcache缓存user信息。
    -->
    <bean id="daoAuthenticationProvider"
        class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userDetailsService" />
        <property name="userCache" ref="userCache" />
    </bean>

 

userDetailsService:根据登录的用户名获取一个UserDetails,即代表一个用户的实体对象。

    <!-- 通过dao查询用户信息 -->
    <bean id="userDetailsService"
        class="org.catspaw.ss2test1.security.UserDetailsSerivceImpl">
        <property name="userDao" ref="userDao" />
    </bean>

 

 UserDetailsSerivceImpl代码

package org.catspaw.ss2test1.security;

import org.catspaw.ss2test1.dao.UserDao;
import org.springframework.dao.DataAccessException;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;

/**
 * 获取UserDetails
 * 使用UserDao查询User
 * 
 * @author 孙宁振
 *
 */
public class UserDetailsSerivceImpl implements UserDetailsService {

	private UserDao userDao;

	public UserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		return userDao.findByUsername(username);
	}
}

 

 UserDao实现(接口省略)

package org.catspaw.ss2test1.dao.hibernate;

import java.util.List;
import org.catspaw.ss2test1.dao.UserDao;
import org.catspaw.ss2test1.model.User;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * 查询User
 * 
 * @author 孙宁振
 *
 */
public class UserDaoHibernate extends HibernateDaoSupport implements UserDao {

	public User get(String id) {
		return (User) getHibernateTemplate().get(User.class, id);
	}

	@SuppressWarnings("unchecked")
	public User findByUsername(String username) {
		DetachedCriteria dc = DetachedCriteria.forClass(User.class);
		dc.add(Expression.eq("username", username));
		List<User> list = getHibernateTemplate().findByCriteria(dc);
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}
}

 

User实体,直接实现了UserDetails

package org.catspaw.ss2test1.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Transient;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;

/**
 * 用户
 * 实现了UserDetails
 * 与Resource多对多关联
 * 
 * @author 孙宁振
 *
 */
@Entity
public class User implements UserDetails {

	private String		id;
	private String		username;
	private String		password;
	private Set<Resource> resources;

	@Id
	public String getId() {
		return id;
	}

	public String getPassword() {
		return password;
	}

	public String getUsername() {
		return username;
	}

	@ManyToMany(targetEntity = Resource.class)
	@JoinTable(name = "user_resource", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "resource_id"))
	public Set<Resource> getResources() {
		return resources;
	}

	@Transient
	public GrantedAuthority[] getAuthorities() {
		Set<Resource> resources = getResources();
		List<GrantedAuthority> grandtedAuthorities = new ArrayList<GrantedAuthority>(
				resources.size());
		for (Resource resource : resources) {
			String authority = resource.getAuthority();
			grandtedAuthorities.add(new GrantedAuthorityImpl(authority));
		}
		return grandtedAuthorities.toArray(new GrantedAuthority[0]);
	}

	@Transient
	public boolean isAccountNonExpired() {
		return true;
	}

	@Transient
	public boolean isAccountNonLocked() {
		return true;
	}

	@Transient
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Transient
	public boolean isEnabled() {
		return true;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setResources(Set<Resource> resources) {
		this.resources = resources;
	}
}

 

 userCache缓存,都是使用的spring提供的实现。

    <bean id="userCache"
        class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
        <property name="cache" ref="userCacheBacked" />
    </bean>
    <bean id="userCacheBacked"
        class="org.springframework.cache.ehcache.EhCacheFactoryBean">
        <property name="cacheManager" ref="cacheManager" />
        <property name="cacheName" value="myUserCache" />
    </bean>
    <bean id="cacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:ehcache-security.xml" />
    </bean>

 ehcache-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir/ehcache-security" />
    <defaultCache maxElementsInMemory="10000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
    <!-- security cache-->
    <cache name="myUserCache" maxElementsInMemory="10000" eternal="false"
        overflowToDisk="true" timeToIdleSeconds="1200" timeToLiveSeconds="7200"
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />        
</ehcache>

 至此认证部分结束,下面是授权部分。

 

 filterSecurityInterceptor,虽然名叫interceptor,实际上是个filter,负责针对要访问的资源进行用户授权,同样也是覆盖默认实现。

    <!-- 
        负责授权的filter,检查Authentication所授予的权限是否可以访问被访问的资源
    -->
    <bean id="filterSecurityInterceptor"
        class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
        <security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" />
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="accessDecisionManager" ref="accessDecisionManager" />
        <!-- 获取访问被访问的资源所需要的权限(authority) -->
        <property name="objectDefinitionSource"
            ref="databaseFilterInvocationDefinitionSource" />
    </bean>

 

 accessDecisionManager,授权管理器,通过多个voter投票判定是否授权,有多种决策机制实现(一票通过,半数通过,一票否决等),具体原理参见参考手册,这里使用的AffirmativeBased是一票通过制,即有一个voter投赞成票就授权。voter会取出当前登录用户的UserDetails的所有authority,与所访问url所对应的authority进行匹配,有相同就通过。

    <!--
        经过投票机制来决定是否可以访问某一资源
        allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过
        其他可选的决策机制:
        ConsensusBased
        UnanimousBased
    -->
    <bean id="accessDecisionManager"
        class="org.springframework.security.vote.AffirmativeBased">
        <property name="decisionVoters">
            <list>
                <bean class="org.springframework.security.vote.RoleVoter">
                    <property name="rolePrefix" value="" />
                </bean>
            </list>
        </property>
    </bean>

 

objectDefinitionSource,获得访问资源所必须具有的权限(authority)。这里和UserDetails的getAuthorities方法刚好相反。

    <!-- 获取访问被访问的资源所需要的权限(authority),以ConfigAttributeDefinition形式返回 -->
    <bean id="databaseFilterInvocationDefinitionSource"
        class="org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource">
        <!-- 匹配url的matcher -->
        <constructor-arg type="org.springframework.security.util.UrlMatcher"
            ref="antUrlPathMatcher" />
        <!-- url对应authority的map -->
        <constructor-arg type="java.util.LinkedHashMap" ref="requestMap" />
    </bean>
    <!--ant path风格的匹配器-->
    <bean id="antUrlPathMatcher"
        class="org.springframework.security.util.AntUrlPathMatcher" />

 

requestMapFactoryBean,实现Spring的FactoryBean接口

这里在容器初始化时就查询所有url和authority的对应关系,保存为一个map,在认证操作时遍历这个map

package org.catspaw.ss2test1.security;

import java.util.LinkedHashMap;
import java.util.List;
import org.catspaw.ss2test1.dao.ResourceDao;
import org.catspaw.ss2test1.model.Resource;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.security.ConfigAttribute;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.SecurityConfig;
import org.springframework.security.intercept.web.RequestKey;

/**
 * 产生一个map,包含所有url:authority的映射
 * key是resourceString(ant表达式,表示一个url集合)(如果是restful风格的应用,则key是url和method)
 * value是访问这些url所需要的权限(authority)
 * 用于设置databaseFilterInvocationDefinitionSource中的requestMap
 * 
 * @author 孙宁振
 *
 */
public class RequestMapFactoryBean implements FactoryBean {

	private ResourceDao										  resourceDao;
	private LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap;

	public void init() {
		requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>();
		List<Resource> resources = resourceDao.findAll();
		for (Resource resource : resources) {
			RequestKey key = new RequestKey(resource.getResourceString());//如果是restful风格的应用,则构造方法的参数应该是url和method
			ConfigAttribute attribute = new SecurityConfig(resource
					.getAuthority());
			ConfigAttributeDefinition definition = new ConfigAttributeDefinition(
					attribute);
			requestMap.put(key, definition);
		}
	}

	public Object getObject() throws Exception {
		if (requestMap == null) {
			init();
		}
		return requestMap;
	}

	public Class getObjectType() {
		return LinkedHashMap.class;
	}

	public boolean isSingleton() {
		return true;
	}

	public void setResourceDao(ResourceDao resourceDao) {
		this.resourceDao = resourceDao;
	}
}

 

ResourceDao实现(接口省略)

package org.catspaw.ss2test1.dao.hibernate;

import java.util.List;
import org.catspaw.ss2test1.dao.ResourceDao;
import org.catspaw.ss2test1.model.Resource;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class ResourceDaoHibernate extends HibernateDaoSupport implements
		ResourceDao {

	@SuppressWarnings("unchecked")
	public List<Resource> findAll() {
		DetachedCriteria criteria = DetachedCriteria.forClass(Resource.class);
		criteria.addOrder(Order.desc("resourceString"));
		return getHibernateTemplate().findByCriteria(criteria);
	}
}

 

Resource实体

package org.catspaw.ss2test1.model;

import java.io.Serializable;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

/**
 * 资源
 * 与User多对多关联
 * 
 * @author 孙宁振
 *
 */
@Entity
public class Resource implements Serializable {

	private String	id;
	private String	authority;	  //ss中权限的标识符
	private String	resourceString; //ant表达式,表示一个url集合
	private Set<User> users;

	@Id
	public String getId() {
		return id;
	}

	public String getAuthority() {
		return authority;
	}

	public String getResourceString() {
		return resourceString;
	}

	@ManyToMany(targetEntity = User.class, mappedBy = "resources")
	public Set<User> getUsers() {
		return users;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setResourceString(String resourceString) {
		this.resourceString = resourceString;
	}

	public void setUsers(Set<User> users) {
		this.users = users;
	}

	public void setAuthority(String authority) {
		this.authority = authority;
	}
}

 

 最后,dao配置

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/ss2test1" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <bean id="abstractSessionFactory" abstract="true">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQL5InnoDBDialect
                </prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
            </props>
        </property>
    </bean>

    <!-- 使用annotation方式描述的SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
        parent="abstractSessionFactory">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
    </bean>

    <bean id="baseDao" abstract="true">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="userDao"
        class="org.catspaw.ss2test1.dao.hibernate.UserDaoHibernate"
        parent="baseDao">
    </bean>
    <bean id="resourceDao"
        class="org.catspaw.ss2test1.dao.hibernate.ResourceDaoHibernate"
        parent="baseDao">
    </bean>

 

hibernate配置文件 hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>    
        <mapping class="org.catspaw.ss2test1.model.User"/>
        <mapping class="org.catspaw.ss2test1.model.Resource"/>
    </session-factory>
</hibernate-configuration>

 

 

本文只是一个最简单的示例,没有遵循rbac规范,仅仅是将user和resource关联起来,一个resource对应一个authority。也没有密码加密,cookie等功能,这些功能配置请参见参考手册。

 

在ss中,授权是以authority为基本单位的,user拥有多个authority,resource也可以拥有多个authority,在授权时只需要将user和resource的authority一一匹配即可。在实际应用中,可以在user和resource增加一层role来解耦,user-role-resource都是多对多关系,authority可以和role对应,授权时就变成了“检查用户是否具有访问某个资源所必须的角色”这一问题。

ss只提供认证和授权两个功能的实现,中间权限分配的实现由程序员负责,不管中间权限分配多么复杂,最后只要能将user和resource用authority关联起来就可以。

 

ss2常用的扩展点有以下几个:

UserDetails,表示一个用户实体,可以通过他来获得用户所具有的authority

AuthenticationProvider,用来认证一个用户Authentication,可以添加多个认证方式,比如sso

accessDecisionManager和Voter,用来对是否允许用户访问进行投票,以及投票的通过策略

objectDefinitionSource,用来获取资源和authority的对应,为用户授权提供依据。

基本上针对这三个扩展点进行相应扩展就可以满足大部分的应用需求。

2.0的整体架构和1.0相比基本没有改变,1.0时代的功能和配置方式也都可以继续使用,如果对ss2的默认配置不太放心,大可以把原来1.0的配置代码copy过来继续使用。

 

附demo
所用到的jar:spring2.0.7,hibernate3.2.5&jpa,spring-security2.0.3,ehcache1.3

数据库:mysql5,建好相应数据库后,把<prop key="hibernate.hbm2ddl.auto">none</prop>的none改为create即可在运行时自动建表
登录入口为/spring_security_login

用户名   密码
admin    admin
aaa      aaa
bbb      bbb

17
0
分享到:
评论
29 楼 nurenok 2010-08-24  
怎么清空缓存是个大问题。,LZ详细解释下。谢谢
28 楼 qqgoodluck 2009-01-03  
孙宁振 写道

qqgoodluck 写道
楼主如何实现动态的资源分配,当我角色可以访问的资源在数据库中发生变动时,如何动态影响到程序。刷新缓存,就是那个userCache,更改角色或资源的时候就清空缓存

谢谢回复,能否加一下我的QQ9975864
你后面的代码有涉及pass一个LinkedHashMap过去,如果我数据库里,角色与资源对应的表中数据发生了改变如何动态影响到系统呢?你后面的代码中的RequestHashMap中资源与角色对应的MAP没有存在缓存中吧?谢谢
27 楼 孙宁振 2008-12-27  
qqgoodluck 写道

楼主如何实现动态的资源分配,当我角色可以访问的资源在数据库中发生变动时,如何动态影响到程序。

刷新缓存,就是那个userCache,更改角色或资源的时候就清空缓存
26 楼 qqgoodluck 2008-12-22  
楼主如何实现动态的资源分配,当我角色可以访问的资源在数据库中发生变动时,如何动态影响到程序。
25 楼 wxlwxq 2008-12-10  
为什么我第一个用户登录后再退出,后面再登录的别的用户也只能进第一个用户能进的页面
24 楼 jillzhang 2008-11-19  
请问我按照您的配置,用了五个表,也是角色对应URL的,但好像永远只有一种角色能访问.
这种角色能访问的话,另一种角色即使有相应的权限也不能访问,是何原因呢?
23 楼 woodding2008 2008-11-06  
孙宁振 写道

bukebushuo 写道
不知道,怎么处理动态的URL,也就是在系统运行中,增加了URL-ROLE,怎样动态的反映到一开始就生成的Map中去?想动态增加url的话可以写一个RequestMap管理bean,把RequestMap注入给它,在需要的时候往map里增加就可以了。


请给段demo 代码。
22 楼 孙宁振 2008-10-26  
引用
楼主,能把你的lib jar包发给我吗?我邮箱wuhongyan008@163.com,先谢谢了

jar太大了,发不动,在框架的官方网站都有,下载相应版本即可
21 楼 孙宁振 2008-10-26  
引用
楼主,你的这种实现方法在每次服务器启动后就把resource表中所有的url对应的权限信息全部读入内存中,以后就不会再从数据库中读取信息了。我想请教两个问题
1.若数据库中resource表被更新了,怎么办呢?
2.若resource表中数据很多,那占用的内存是不是太多了点?

呵呵,我这只是个简单的demo,实际应用肯定不能这样的
1,更新时同时刷新cache
2,改成dao+cache实现
20 楼 wuhongyan008 2008-10-24  
楼主,你的这种实现方法在每次服务器启动后就把resource表中所有的url对应的权限信息全部读入内存中,以后就不会再从数据库中读取信息了。我想请教两个问题
1.若数据库中resource表被更新了,怎么办呢?
2.若resource表中数据很多,那占用的内存是不是太多了点?
19 楼 wuhongyan008 2008-10-23  
楼主,能把你的lib jar包发给我吗?我邮箱wuhongyan008@163.com,先谢谢了
18 楼 talangniao 2008-10-16  
是由于用户放置到缓存的缘故,增加用户、权限的时候没有清空缓存
17 楼 talangniao 2008-10-16  
Possible error: Filters at position 2 and 3 are both instances of

这个问题怎么不能去掉?难道没有影响嘛?
16 楼 talangniao 2008-10-15  
为什么设置url资源和权限后,需要从新启动tomcat,设置的用户才拥有相应的权限。  或者是修改某个用户的权限,并没有马上生效,拥有的权限还是原来的。重启tomcat后就生效。这到底是什么原因?
15 楼 qatang 2008-08-29  
高手高手高高手!经测试,成功!
14 楼 孙宁振 2008-08-29  
引用
又出现一个问题。当页面session超时后,我再点击的话,就会跳转到spring security自己默认的那个登录页面去了。怎么才能设定为自己的超时页??

这确实是个没考虑到的问题。。。
还是因为ss2的默认配置。里边有一个默认authenticationProcessingFilterEntryPoint,负责根据认证或授权抛出的异常跳转错误页。当认证过成中出现AuthenticationException的时候他会找默认的登录页面。
如果想自定义错误页的话得覆盖默认的authenticationProcessingFilterEntryPoint。
<security:http auto-config="true" access-denied-page="/accessDenied.html"
entry-point-ref="authenticationProcessingFilterEntryPoint">
加一个entry-point-ref,指向一个bean
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl"
value="/login.jsp" />
<property name="forceHttps" value="false" />
</bean>
这样当认证失败时就会跳到/login.jsp了
13 楼 qatang 2008-08-29  
又出现一个问题。当页面session超时后,我再点击的话,就会跳转到spring security自己默认的那个登录页面去了。怎么才能设定为自己的超时页??
12 楼 40020072 2008-08-20  
引用
access-denied-page="/error.jsp"



我试过是起作用的~

楼主的研究很棒~
11 楼 孙宁振 2008-08-19  
引用
access-denied-page="/error.jsp"没起作用,直接跳到resin的错误去了

resin没研究过,我用tomcat测试的
10 楼 qatang 2008-08-19  
<!--
        2.0新增的命名空间,使得配置简化了很多
        auto-config 自动使用默认的配置
        access-denied-page 指定访问未授权页面时显示的页面
    -->
    <security:http auto-config="true" access-denied-page="/error.jsp">
        <security:anonymous granted-authority="AU_BASIC" />
    </security:http>


access-denied-page="/error.jsp"没起作用,直接跳到resin的错误去了
403 Access is denied

Resin-3.0.25 (built Wed, 05 Dec 2007 08:19:34 PST) 


这是什么原因?谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics