spring security自定义AccessDeniedException权限异常处理

项目中需要根据url获取此url的权限,并做判断,若权限不足,throw new AccessDeniedException异常

 

项目中大多数前台访问请求为ajax请求,若为ajax请求,一般的需求为:若权限不足,直接前台提示,不做权限不足页面的跳转。

当然,为了满足可能某些项目会有<a>标签的超链接直接访问,还是在实现类里面做了两层判断

前提条件:

1,已经做了url的判断

authentication代表用户所拥有的权限,object代表url,
configAttributes代表请求url所需要的资源,

此方法为实现AccessDecisionManager后重写的方法

	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		if(configAttributes == null) {
			return;
		}
		//所请求的资源拥有的权限(一个资源对多个权限)
		Iterator<ConfigAttribute> iterator = configAttributes.iterator();
		while(iterator.hasNext()) {
			ConfigAttribute configAttribute = iterator.next();
			//访问所请求资源所需要的权限
			String needPermission = configAttribute.getAttribute();
			//用户所拥有的权限authentication
			for(GrantedAuthority ga : authentication.getAuthorities()) {
				if(needPermission.equals(ga.getAuthority())) {
					return;
				}
			}
		}
		//没有权限
		throw new AccessDeniedException("没有权限");
	}

2,spring-security.xml配置

<security:access-denied-handler ref="accessDeniedHandler"></security:access-denied-handler>
       <bean  id="accessDeniedHandler" class="com.infoland.security.CustomAccessDeniedHandler">
       		<property name="errorPage" value="/permissionerror.jsp"/>
       </bean>

3,具体实现类

/**
 * @Auther: lixiupeng
 * @Date: 2018/11/21 15:54
 * @Description: 自定义权限不足处理
 */
@Service
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    private String errorPage;

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {


        //判断是否为ajax请求
        if (httpServletRequest.getHeader("accept").indexOf("application/json") > -1
                || (httpServletRequest.getHeader("X-Requested-With") != null && httpServletRequest.getHeader("X-Requested-With").equals(
                "XMLHttpRequest"))) {
            //设置状态为403,无权限状态
            httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
            //设置格式以及返回json数据 方便前台使用reponseJSON接取
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json; charset=utf-8");
            PrintWriter out = httpServletResponse.getWriter();
            JSONObject json = new JSONObject();
            json.put("message","权限不足,请联系管理员");
            out.append(json.toString());
        }else if(!httpServletResponse.isCommitted()){//非ajax请求
            if(errorPage!=null){
                // Put exception into request scope (perhaps of use to a view)
                httpServletRequest.setAttribute(WebAttributes.ACCESS_DENIED_403, e);

                // Set the 403 status code.
                httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);

                // forward to error page.
                RequestDispatcher dispatcher = httpServletRequest.getRequestDispatcher(errorPage);
                dispatcher.forward(httpServletRequest, httpServletResponse);
            }else{
                httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN,e.getMessage());
            }
        }
    }

    public void setErrorPage(String errorPage) {
        if ((errorPage != null) && !errorPage.startsWith("/")) {
            throw new IllegalArgumentException("errorPage must begin with '/'");
        }
        this.errorPage = errorPage;
    }
}

若xml配置中,需要配置自定义的jsp或者html,则实现类必须书写errorpage(名称自定义)以及set方法

若不配置errorpage,则会自动跳转系统默认的403页面

 

Spring Security 中,可以通过自定义实现 `AccessDecisionManager` 接口来实现授权的具体逻辑。 首先,创建一个实现了 `AccessDecisionManager` 接口的自定义类。该类需要实现接口中的 `decide` 方法,该方法负责根据用户的权限和访问请求的权限要求,决定用户是否有访问权限。 ```java import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import java.util.Collection; public class CustomAccessDecisionManager implements AccessDecisionManager { @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException { // 获取用户的权限 Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); // 遍历访问请求所需的权限 for (ConfigAttribute configAttribute : configAttributes) { // 判断用户是否具有所需的权限 for (GrantedAuthority authority : authorities) { if (configAttribute.getAttribute().equals(authority.getAuthority())) { return; // 用户具有所需的权限,放行 } } } throw new AccessDeniedException("Access Denied"); // 用户没有访问权限,抛出异常 } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class<?> clazz) { return true; } } ``` 接下来,需要在 Spring Security 的配置类中配置使用自定义的 `AccessDecisionManager`。例如,在 `WebSecurityConfigurerAdapter` 的子类中,可以重写 `configure` 方法来配置自定义的 `AccessDecisionManager`。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // ...其他配置... .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .accessDecisionManager(accessDecisionManager()) // 配置自定义AccessDecisionManager .and() // ...其他配置... } @Bean public AccessDecisionManager accessDecisionManager() { return new CustomAccessDecisionManager(); } } ``` 在上述示例中,使用了`.accessDecisionManager(accessDecisionManager())`方法来配置自定义的 `AccessDecisionManager`。 通过以上步骤,就可以实现自定义授权的具体实现。当用户访问需要授权的资源时,`CustomAccessDecisionManager` 中的 `decide` 方法会被调用,根据用户的权限和资源的权限要求进行判断,并决定是否有访问权限
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值