最近项目开发中有这样一个业务逻辑,一个登陆画面,根据不同权限跳转到不同的画面(Action)
开始的做法是直接跳到一个调度的Action,再由这个Action去分配。
这次开发使用了安全框架,遂希望通过安全框架去做这个调度
于是使用authentication-success-handler-ref
来替换default-target-url和always-use-default-target,实现这一目的
国际惯例,先上代码
authentication-success-handler-ref="authenticationDispatcher"是至关重要的,当登陆成功会调用实现AuthenticationSuccessHandler接口的onAuthenticationSuccess方法.
下面是实现类
开始的做法是直接跳到一个调度的Action,再由这个Action去分配。
这次开发使用了安全框架,遂希望通过安全框架去做这个调度
于是使用authentication-success-handler-ref
来替换default-target-url和always-use-default-target,实现这一目的
国际惯例,先上代码
- <http auto-config='true' >
- <intercept-url pattern="/public/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
- <intercept-url pattern="/user/**" access="ROLE_SPACE_ADMIN,ROLE_SMALL_SPACE_ADMIN,ROLE_INSTITUTION_MEMBER,ROLE_SYSTEM_ADMIN"/>
- <intercept-url pattern="/admin/**" access="ROLE_SUPER_ADMIN"/>
- <form-login login-page="/user/login.action"
- authentication-failure-url="/user/login.action?msg=fault"
- authentication-success-handler-ref="authenticationDispatcher"
- login-processing-url="/securityLogin"/>
- <logout logout-success-url="/user/login.action" logout-url="/securityLogout"/>
- </http>
- <beans:bean id="authenticationDispatcher" class="com.lstp.service.security.impl.LstpAuthenticationSuccessHandler">
- <beans:property name="authDispatcherMap">
- <beans:ref local="dispatcherMap"/>
- </beans:property>
- </beans:bean>
- <beans:bean id="dispatcherMap" class="java.util.HashMap">
- <beans:constructor-arg>
- <beans:map>
- <beans:entry key="ROLE_SPACE_ADMIN" value="/user/userSpace.action"/>
- <beans:entry key="ROLE_SMALL_SPACE_ADMIN" value="/user/userSpace.action"/>
- <beans:entry key="ROLE_INSTITUTION_MEMBER" value="/user/userSpace.action"/>
- <beans:entry key="ROLE_SYSTEM_ADMIN" value="/admin/adminSpace.action"/>
- <beans:entry key="ROLE_SUPER_ADMIN" value="/admin/adminSpace.action"/>
- </beans:map>
- </beans:constructor-arg>
- </beans:bean>
authentication-success-handler-ref="authenticationDispatcher"是至关重要的,当登陆成功会调用实现AuthenticationSuccessHandler接口的onAuthenticationSuccess方法.
下面是实现类
- package com.lstp.service.security.impl;
- import java.io.IOException;
- import java.util.Collection;
- import java.util.Map;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.authority.GrantedAuthorityImpl;
- import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
- import org.springframework.util.Assert;
- /**
- * 权限登录成功句柄
- * 该类为平台成功跳转到多个入口提供依据
- * @author ryuu-kk
- *
- */
- public class LstpAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
- /**
- * url参数
- */
- private Map<String, String> map;
- /**
- * 多role选择,默认取得权限表第一个权限
- */
- private boolean isFirst = true;
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request,
- HttpServletResponse response, Authentication authentication)
- throws IOException, ServletException {
- Assert.notNull(map, "AuthInterceptMap is null!");
- String url = "";
- Collection<GrantedAuthority> authCollection = authentication.getAuthorities();
- if (authCollection.isEmpty()) {
- return;
- }
- //对于一个登录用户有多种角色,只取得第一个
- if (isFirst) {
- GrantedAuthority[] a = new GrantedAuthorityImpl[]{};
- url = map.get(authCollection.toArray(a)[0].toString());
- response.sendRedirect(request.getContextPath() + url);
- return;
- }
- //选择取得最后一个role掉转;这里一个用户的多个角色较少
- //迭代的速度比转换成数组的速度要快
- for (GrantedAuthority auth : authCollection) {
- url = map.get(auth.getAuthority());
- }
- response.sendRedirect(url);
- }
- /**
- * 权限跳转依据
- * @param map 参数
- * key:url
- * value:role
- */
- public void setAuthDispatcherMap(Map<String, String> map) {
- this.map = map;
- }
- /**
- * 多种角色方案
- * 设置是否只取得第一个role
- * @param isFirst true:多种角色只取第一个,false:取得最后一个
- */
- public void setMultipleAuth(boolean isFirst) {
- this.isFirst = isFirst;
- }
- }