码迷,mamicode.com
首页 > 编程语言 > 详细

SpringSecurity应用中遇到的问题

时间:2015-07-26 14:20:59      阅读:998      评论:0      收藏:0      [点我收藏+]

标签:spring security   安全   框架   spring   aop   

(一) Spring Security简介

一句话书面用语:Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架(目前最新是Spring Security 4.0版本,2015,07,10)。

只要知道Spring Security是基于Spring AOP和Servlet过滤器实现的安全性框架,解决Web应用中的安全问题,安全问题主要包含两个方面:

1.   认证(authentication)

2.   授权(authorization,或者叫访问控制)

认证解决“你是谁“ 的问题,而授权解决”你可以干啥“的问题。

(二)Spring Security应用

网上很多SpringSecurity应用详解,但是第一次使用还是碰到很多问题,这里讲自己遇到的问题记录下来,希望对需要的朋友有些帮助。首先介绍下Demo的一些基本信息:界面用JSP,后台S2SH

1.SpringSecurity用户认证策略(最常使用的是 实现UserDetailsService接口的用户数据库认证)

所谓用户认证策略,说白了就是你输入登录名和密码后,程序如何验证该用户名和密码是否有效。SpringSecurity提供很多用户认证策略,比如:基于内存,JDBCLDAP等。最常用到的是从数据库中查询该登录用户的用户名和密码是否有效),所以基于JDBC的认证方式是一种选择;但是在我们的Web应用中,肯定有关于用户的增删改查方法的实现。这样的话采用实现UserDetailsService接口的方式进行用户认证会方便很多。下面是具体实现的代码:

@Service("userDetailsService")

publicclassUserDetailsServiceImpl implements UserDetailsService {

   @Resource

   private UserService userService; 

   @Override

   public UserDetails  loadUserByUsername(String username)throws UsernameNotFoundException {

      // TODO Auto-generated method stub

      Users user = userService.getUserByUserName(username);

      MyUserDetails u = null;

      intid = user.getId();

      String section = user.getSection();

      String userName = user.getUserName();

      if(user != null){

           u= new MyUserDetails(username,user.getPassword(),id,section,userName,findUserAuthorities(user));

      }
      return u;

   }
    publicList<GrantedAuthority> findUserAuthorities(Users user){ 

       List<GrantedAuthority> autthorities = new ArrayList<GrantedAuthority>(); 

       List<Permission> roles =  userService.getPermissionByUser(user);

        for (Permission role : roles) { 

            autthorities.add(newSimpleGrantedAuthority(role.getRoleCode()));

        } 
        return  autthorities;
    } 

}

对以上代码解析:

1.UserDetailsServiceSpring Security中的接口,其内只定义了一个方法: UserDetailsloadUserByUsername(String username)

当用户提交登陆表单后,SpringSecurity框架就会调用loadUserByUsername方法,传入的参数username就是登录表单中的name=”j_username” 的标签值,返回一个UserDetails对象。

UserDetails也是Security框架中的接口,并且框架中也有一个默认的实现类User,但是User只有usernamepasswordauthorities属性,可是在Web应用中我们经常会用到用户的其他信息(比如,userIdemailage等),这种情况下我们可以不用SpringSecurityUser类,自定义一个类,但是必须实现UserDetails接口,并且必须包含usernamepasswordauthorities三个属性(其他属性根据自己的需要可以任意添加),本例中就是MyUserDetails,属性包含(usernamepasswordsection部门)。

 (2. @Resource

private UserService userService;  

这个是自定义的提供用户增删改查的service接口(很多应用应该都会有)

(3). Users user = userService.getUserByUserName(username);

这里的Users是程序中自定义的用户类,通过userService的getUserByUserName获取Users对象。

 

 

下面列出的是使用SpringSecurity过程中遇到的问题:

 

1.接收不到j_username参数问题

开始的登陆界面中的form表单中用户名和密码的input标签分别是:

<form name="form" method="post"action="j_spring_security_check">

 

<input name="j_username"id="j_username" type="text"/>

<input name="j_password"id="j_password " type="text"/>

 

</form>

这是默认的参数名,form中的action属性值"j_spring_security_check" 也是默认的,但是表单提交后,之前提到的loadUserByUsernameString username方法中无法接受到j_username参数。

解决方法:在<form-login >中添加username-parameter和password-parameter属性,显示的指定接受的参数名称。

如下:

<form-login login-page=‘/manage/login.jsp‘

            username-parameter=‘j_username‘

            password-parameter=‘j_password‘

            />

2.<sec:authorize>无效问题(ROLE_开头)

SpringSecurity提供了视图级别的保护,即我们使用不同的身份登录,通常需要显示的界面不同,比如管理员登录时可以进行增删改查操作,但是普通用户可能只能查看,增加,修改,删除的按钮此时就不需要显示了。

如下所示:

<sec:authorize access="hasRole(‘ROLE_ADMIN‘)">

<a href="manage/user/userAction-userAdd.do">新增</a>

</sec:authorize>

此时登录用户拥有ROLE_ADMIN身份是才会显示“新增”按钮。但是有时<sec:authorize>标签会无效,这是因为角色必须以RLOE_开头才能被识别。

 

3无法请求Struts2的Action(CSRF,403 Forbidden)

<a href="manage/user/userAction-userAdd.do">新增</a>

程序中出现上面这个按钮,点击过后我希望跳转到添加用户的界面,但此时可能出现点击过后,没有跳转到用户新增页面。这时FireDebug控制台出现403Forbidden错误提示。

这是应为SpringSecurity框架提供了预防CSRF(跨站请求伪造)的功能。在提交请求时,该请求被CrsfFilter拦截,验证_crsf的token是否有效。

注意:只有在使用POST方法提交时才会被拦截。

解决方法有两种:

(1)禁用此功能,只要在<http >标签内配置一下元素即可。

<http 。。。>

 。。。。。

 <csrf disabled="true"></csrf><!--  防止跨站请求伪造攻击 -->

</http >

(2)提供验证需要的token。如下所示:

<a href="manage/user/userAction-userAdd.do? ${_csrf.parameterName}=${_csrf.token}">新增</a>

 

4,iframe加载问题(x-frame-options)

当我们的jsp页面中使用了iframe时,可能出现该iframe中的内容无法加载的问题。

这是因为SpringSecurity提供的HeaderWriterFilter为response添加安全header信息。

其中就有一项是:X-Frame-Options选项。

该选项有三个值:

      DENY:浏览器拒绝当前页面加载任何frame页面。

      SAMEORIGHT:允许加载本站点内的页面。

      ALLOW-FROM:允许frame加载任何页面。

SpringSecurity中默认设置X-Frame-Options的值为DENY(可以从FireDebug中查看)

解决方法:

禁止HeaderWriterFilter为response添加安全header信息。如下:

<http 。。。>

 。。。。。

<!-- 配置HeaderWriterFilter,为response添加安全header信息-->

<headers defaults-disabled="true">

   <cache-control/>

</headers>

。。。。

</http >

 

5.<http>元素及其子元素的常用属性

SpringSecurity是基于过滤器实现自己的安全功能的,所以有必要知道常用的过滤器的配置(xml形式)及功能。这些过滤器基本是在<http>元素内配置的,下面就介绍下常用的配置。

<http>元素

包含的属性:

      auto-config=”true” : 自动配置是个默认的过滤器。

      use-expressions=“true”:允许使用EL-expressions。

     。。。。


下面是<http>元素的子元素:

(1)<form-login>(添加UsernamePasswordAuthenticationFilter过滤器)

属性:

      login-page:登录界面的url,如:       login-page=‘/manage/login.jsp‘

      username-parameter:request中包含username的参数名,默认username,

      password-parameter:同上,默认是password。

注意(SpringSecurity4之前默认都是j_username,j_password,这点要注意)

      login-processing-url:处理登录请求的url,     这里的值必须和jsp页面中form表单的action的值一致。

      authentication-failure-url:认证失败跳转页面url。

      default-target-url:验证成功默认跳转的页面url。

      always-use-default-target:若为true,始终default-target-url指定页面进入系统。

     

(2)<access-denied-handler>(用户被拒绝访问作何处理,比如返回一个错误界面)

属性:

error-page : 被拒绝访问后,返回errorpage的url地址。

      ref:指向AccessDeniedHandler类型的bean。

(3)<headers>(前面提到过,该元素用来配置response的header信息)

属性:

      defaults-disabled :可选,禁止response的默认header信息。默认为false(即header中包含默认的基本信息)

      disabled:可选,默认false。


待续。。。。

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

SpringSecurity应用中遇到的问题

标签:spring security   安全   框架   spring   aop   

原文地址:http://blog.csdn.net/topgun_viper/article/details/47067119

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!