SpringSecurity应用中遇到的问题

(一) 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提供很多用户认证策略,比如:基于内存,JDBC,LDAP等。最常用到的是从数据库中查询该登录用户的用户名和密码是否有效),所以基于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).UserDetailsService是Spring Security中的接口,其内只定义了一个方法:
UserDetailsloadUserByUsername(String
username)

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

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

(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" 也是默认的,但是表单提交后,之前提到的loadUserByUsername(String 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。

待续。。。。

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

时间: 2024-10-22 01:45:30

SpringSecurity应用中遇到的问题的相关文章

SpringSecurity数据库中存储用户、角色、资源

这几天项目中用到了SpringSecurity做登陆安全.所以在这写一下也许可以帮助一下其他人,自己也熟悉一下 SpringSecurity配置文件如下: <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w

springsecurity基于数据库验证用户

之前的springsecurity程序都是将数据存放在内存中的,通过 1 <security:user-service> 2 <security:user name="user" password="user" authorities="ROLE_USER"/> 3 <security:user name="admin" password="admin" authorities

SpringSecurity学习三----------通过Security标签库简单显示视图

描述:本篇博客在上一博客基础上实现利用SpringSecurity标签库控制页面显示权限.代码为完整代码,复制即可使用. 1.项目结构 2.pom.xml 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.

SpringBoot20 集成SpringSecurity02 -&gt; 利用SpringSecurity进行前后端分离的登录验证

1 SpirngBoot环境搭建 创建一个SpringBoot项目即可,详情参见三少的相关博文 参考博文 -> 点击前往 SpirngBoot项目脚手架 -> 点击前往 2 引入SpirngSecurity依赖 技巧01:引入了springSecurity相关依赖后,项目就会被SpringSecurity进行管理了:默认的登录名为user,登录密码会被打印到控制台上 技巧02:SpringSecurity默认的配置使用的是 <!--spring-security相关--> <

spring boot跨域请求访问配置以及spring security中配置失效的原理解析

一.同源策略 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[origin]就是协议.域名和端口号.例如:http://www.baidu.com:80这个URL. 什么是同源 若地址里面的协议.域名和端口号均相同则属于同源. 是否是同源的判断 例如判断下面的URL是否与 http://www.a.com/test/index.html 同源 http://www.a

【使用篇二】SpringBoot集成SpringSecurity(22)

SpringSecurity是专门针对基于Spring项目的安全框架,充分利用了依赖注入和AOP来实现安全管控.在很多大型企业级系统中权限是最核心的部分,一个系统的好与坏全都在于权限管控是否灵活,是否颗粒化.在早期的SpringSecurity版本中我们需要大量的xml来进行配置,而基于SpringBoot整合SpringSecurity框架相对而言简直就是太简单了. SpringSecurity框架有两个概念认证和授权,认证可以访问系统的用户,而授权则是用户可以访问的资源. 1. 构建项目 加

java.lang.NoSuchMethodError: org.springframework.web.context.ConfigurableWebApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment;问题

在springsecurity学习中,在加入spring有关的jar包后,出现java.lang.NoSuchMethodError: org.springframework.web.context.ConfigurableWebApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment报错 出错原因:jar包版本有冲突 解决方法:换不同版本的jar包就可以解决问题了

SpringSecurity-ChannelProcessingFilter的作用

ChannelProcessingFilter决定的是web请求的通道,即http或https. 在springsecurity配置文件中添加这样一行 <intercept-url pattern='/**' requires-channel='https' /> ChannelProcessingFilter就会检查这个请求走的是否是https.如果是,就继续向下执行.否则,自动切换到对应的channel! ChannelProcessingFilter有一个成员变量ChannelDecis

spring security实现限制登录次数功能

本节是在基于注解方式进行的,后面的例子都会基于注解形式,不再实现XML配置形式,毕竟注解才是趋势嘛! 关键在于实现自定义的UserDetailsService和AuthenticationProvider 项目结构如下: 查看spring security的源代码可以发现默认security已经定义的user中的一些变量,鉴于此创建users表如下: CREATE TABLE users ( username VARCHAR(45) NOT NULL, password VARCHAR(45)