SpringSecurity安全配置—SSH整合

SpringSecurity安全配置—SSH整合

项目中使用了SpringSecurity,发现SpringSecurity实现登录管理很方便,花了一点时间,将SpringSecurity安全配置整理出来,实现SpringSecurity安全配置登陆,供需要的朋友参考,如有整理不到位的地方,请提出意见,谢谢!

使用Springsecurity首先要提的就是jar包了,Springsecurity的jar下载地址:http://static.springsource.org/spring-security/site/downloads.html。不过我的项目里的jar包比较旧点了,是从项目抽取出来的,所需jar如下:

第1步:新建一个web工程,将Springsecurity的jar添加到web工程中WEB-INF中lib中,本DEMO中整合了Struts2,Hibernate,Spring,编写web.xml,具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <!-- 加载Spring的配置文件 -->
  <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext*.xml</param-value>
  </context-param>

  <!-- 中文过滤器 -->
  <filter>
  <filter-name>chinese</filter-name>
  <filter-class>com.filter.EncodingFilter</filter-class>
  </filter>
  
  <!-- 检测是否登陆过滤器 -->
  <filter>
  <filter-name>loginFilter</filter-name>
  <filter-class>com.filter.LoginFilter</filter-class>
  
  <!-- sessionKey:需检查的在 Session 中保存的关键字 -->
  <init-param>
  <param-name>sessionKey</param-name>
  <param-value>LOGIN_NAME</param-value>
  </init-param>
  
  <!-- redirectURL:如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath  -->
  <init-param>
  <param-name>redirectURL</param-name>
  <param-value>/user/login.htm</param-value>
  </init-param>
  
  <!-- notCheckURLList:不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath  -->
  <init-param>
  <param-name>notCheckURLList</param-name>
  <param-value>/user/login.htm;/user/my.htm;</param-value>
  </init-param>
  </filter>
  
  <!-- 控制Session的开关 -->
  <filter>
  <filter-name>openSession</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  </filter>
  
  <!--
    Spring security Filter(注意配置文件的Filter的位置,否则SpringSecurityUtils.getCurrentUser()出现空指针异常。)
  在web.xml文件中加入Filter声明: 这个Filter会拦截所有的URL请求,并且对这些URL请求进行Spring Security的验证
  注意:
  1、springSecurityFilterChain这个名称是由命名空间默认创建的用于处理web安全的一个内部的bean的id。所以在Spring配置文件中,不应该再使用这个id作为你的bean。 
  2、登录action:/spring_security_login
  3、 登出action:j_spring_security_logout (这两个action是springSecurity自带的,直接用就可以了)
4、 Filter的配置,在项目中,跟struts2一起使用,filter的前后顺序有关系。Spring secutiry要放在struts2的前面,否则系统找不到security的action
5、 怎么获取用户信息:可以参考springside中的实现org.springside.modules.security.springsecurity.SpringSecurityUtils。具体信息都在Authentication这个类中。
  -->
  <filter> 
    <filter-name>springSecurityFilterChain</filter-name>  
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  </filter>
  
   <!-- Struts2配置 -->
  <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  
  <filter-mapping>
  <filter-name>chinese</filter-name>
  <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  <filter-name>openSession</filter-name>
  <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>  
  </filter-mapping>
  
   <filter-mapping>
  <filter-name>loginFilter</filter-name>
  <url-pattern>*.htm</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>*.htm</url-pattern>
  </filter-mapping>


 <!-- Spring的监听器 -->
  <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


第2步:编写LoginFilter.java,用于过滤校验用户是否登陆,具体如下:

/**
 * @Discription: 登陆过滤器:
 * 用于检测用户是否登陆的过滤器,如果未登录,则重定向到指的登录页面 
 * 配置参数:
 * sessionKey:需检查的在 Session 中保存的关键字
 * redirectURL:如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath 
 * notCheckURLList:不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath
 * @Project: SpringSecurity
 * @Package: com.filter
 * @Title: LoginFilter.java
 * @author: [heyong]
 * @date 2012-4-21
 * @version 1.0
 * @update [日期YYYY-MM-DD] [更改人姓名]
 */
public class LoginFilter implements Filter{

/**
* <p>Discription:[logger日志]</p>
*/
private static Log logger = LogFactory.getLog(LoginFilter.class);

/**
* <p>Discription:[需检查的在 Session 中保存的关键字]</p>
*/
private String sessionKey = null;

/**
* <p>Discription:[如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath ]</p>
*/
private String redirectURL = null;

/**
* <p>Discription:[不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath]</p>
*/
private List<String> notCheckURLList = new ArrayList<String>();

public void destroy() {
notCheckURLList.clear();
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request    = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

// 获得Session
HttpSession session = request.getSession();

// 判断sessionKey 是否为空
if(StringUtils.isEmpty(sessionKey)){
filterChain.doFilter(request, response);
return;
}

if (!checkRequestURIIntNotFilterList(request)) {
UserDetail userDetail = null;
try {
// 取得当前用户登陆的信息
userDetail = (UserDetail)SpringSecurityUtils.getCurrentUser();
} catch (Exception e) {
logger.info("Event=[LoginFilter#doFilter] redirect:".concat(request.getContextPath().concat(redirectURL)));
response.sendRedirect(request.getContextPath().concat(redirectURL));
return;
}

// 判断是否登陆
if (userDetail == null || userDetail.getUserId() == null) {
response.sendRedirect(request.getContextPath().concat(redirectURL));
return;
}

// 在userDetail中得到用户信息
SysStUser user = userDetail.getCurrentUser();

// UserDetail 存在,测检查Session是否存在,若不存在则,初始化Session
if (session.getAttribute(sessionKey) == null) {
logger.info("Event=[LoginFilter#doFilter] sessionKey: " + sessionKey);
session.setAttribute(sessionKey, user);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}

public void init(FilterConfig filterConfig) throws ServletException {
sessionKey     = filterConfig.getInitParameter("sessionKey");
redirectURL    = filterConfig.getInitParameter("redirectURL");
String urlList = filterConfig.getInitParameter("notCheckURLList");

if (StringUtils.isNotEmpty(urlList)) {
StringTokenizer st = new StringTokenizer(urlList, ";");
notCheckURLList.clear();
while (st.hasMoreTokens()) {
notCheckURLList.add(st.nextToken());
}
}
}

/**
* @Description: 检测当前访问URL,是否有过滤掉的URL。
* @author [heyong]
* @date 2012-4-21
* @version 1.0
* @param request
* @return
* @update:[日期YYYY-MM-DD] [更改人姓名]
*/
private boolean checkRequestURIIntNotFilterList(HttpServletRequest request) {
        String url = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo());
        return notCheckURLList.contains(url);
    }
}

第3步:提供一个UserDetail.java,该类继承org.springframework.security.userdetails.User类,用于保存一些自定义的业务数据,具体如下:

/**
 * @Discription: UserDetail继承User
 * @Project: SpringSecurity
 * @Package: com.security
 * @Title: UserDetail.java
 * @author: [heyong]
 * @date 2012-4-21
 * @version 1.0
 * @update [日期YYYY-MM-DD] [更改人姓名]
 */
public class UserDetail extends User {
/**
* <p>Discription:[serialVersionUID]</p>
*/
private static final long serialVersionUID = 5533186529087001787L;

/**
* 用户ID
*/
private String userId;

/**
* 用户真实姓名
*/
private String realName;

/**
* 当前登录的用户信息
*/
private SysStUser currentUser;

public UserDetail(String userId, String realName, String username,String password, GrantedAuthority[] authorities) {
super(username, password, true, true, true, true, authorities);
this.userId = userId;
this.realName = realName;
}

public UserDetail(String username, String password, boolean enabled,
          boolean accountNonExpired, boolean credentialsNonExpired,
          boolean accountNonLocked, GrantedAuthority[] authorities)throws IllegalArgumentException {
super(username, password, enabled, accountNonExpired,credentialsNonExpired, accountNonLocked, authorities);
}

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public String getRealName() {
return realName;
}

public void setRealName(String realName) {
this.realName = realName;
}

public SysStUser getCurrentUser() {
return currentUser;
}

public void setCurrentUser(SysStUser currentUser) {
this.currentUser = currentUser;
}
}

第4步:提供一个UserDetailsServiceImpl.java,该类实现org.springframework.security.userdetails.UserDetailsService类,必须实现loadUserByUsername()方法,具体如下:

/**
 * @Discription: UserDetailsServiceImpl实现UserDetailsService接口,实现UserDetailsService类中loadUserByUsername()方法
 * @Project: SpringSecurity
 * @Package: com.iservices
 * @Title: UserDetailsServiceImpl.java
 * @author: [heyong]
 * @date 2012-4-20
 * @version 1.0
 * @update [日期YYYY-MM-DD] [更改人姓名]
 */
public class UserDetailsServiceImpl implements UserDetailsService{

/**
* 用户信息Services(自已提供查询Services查询接口)
*/
private UsersServices usersServices;

/**
* @Description: 实现loadUserByUsername(),根据用户名明查询用户的信息
* @author [heyong]
* @date 2012-4-20
* @version 1.0
* @param LoginName:登陆用户名
* @return
* @throws UsernameNotFoundException
* @throws DataAccessException
* @update:[日期YYYY-MM-DD] [更改人姓名]
*/
public UserDetails loadUserByUsername(String LoginName)throws UsernameNotFoundException, DataAccessException {
SysStUser sysStUser = usersServices.searchSysUserByLoginName(LoginName);
if (sysStUser != null) {
UserDetail userdetail = new UserDetail(sysStUser.getId(), sysStUser.getUserRname(), sysStUser.getUserName(),sysStUser.getUserPwd(),new GrantedAuthority[0]);
userdetail.setCurrentUser(sysStUser);
return userdetail;
}
return null;
}

public void setUsersServices(UsersServices usersServices) {
this.usersServices = usersServices;
}
}

第5步:提供一个ResourceDetailsServiceImpl.java,该类实现org.springside.modules.security.springsecurity.ResourceDetailsService类,必须实现getRequestMap()方法,具体如下:

/**
 * 从数据库查询URL--授权定义Map的实现类.
 */
public class ResourceDetailsServiceImpl implements ResourceDetailsService {
public LinkedHashMap<String, String> getRequestMap() throws Exception {
return new LinkedHashMap<String, String>();
}
}


第6步:前面基础的java实现类都已将准备完成了,接下来重要的一步来了。在web工程的src目录下新建一个applicationContext-security.xml,用于SpringSecurity安全配置,具体如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:s="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"
default-autowire="byType" default-lazy-init="true">

<description>SpringSecurity安全配置</description>

<!-- 
http安全配置:
1、default-target-url:默认的目标路劲,指定登陆成功,跳转的页面
2、authentication-failure-url:指定登陆失败,跳转页面
3、logout-success-url:登录成功后,退出,跳转URL
--> 
<s:http auto-config="true" access-decision-manager-ref="accessDecisionManager"> 
<s:form-login login-page="/webapp/login.jsp"  default-target-url="/user/queryUsersAll.htm" authentication-failure-url="/user/login.htm?error=true" /> 
<s:logout logout-success-url="/user/login.htm" invalidate-session="true"/> 
<s:remember-me key="e37f4b31-0c45-11dd-bd0b-0800200c9a66" /> 
</s:http>

<!-- 认证配置认证管理器。用户名密码都集成在配置文件中 -->
<s:authentication-provider user-service-ref="userDetailsService">
<!-- 可设置hash使用sha1或md5散列密码后再存入数据库 -->
<s:password-encoder hash="plaintext" />
</s:authentication-provider>

<!-- 项目实现的用户查询服务(第4步提供的UserDetailsServiceImpl.java类) -->
<bean id="userDetailsService" class="com.security.UserDetailsServiceImpl">
<property name="usersServices" ref="usersServicesImpl"></property>
</bean>

<!-- 重新定义的FilterSecurityInterceptor,使用databaseDefinitionSource提供的url-授权关系定义 -->
<bean id="filterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
<s:custom-filter before="FILTER_SECURITY_INTERCEPTOR" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="objectDefinitionSource" ref="databaseDefinitionSource" />
</bean>

<!-- DefinitionSource工厂,使用resourceDetailsService提供的URL-授权关系. -->
<bean id="databaseDefinitionSource" class="org.springside.modules.security.springsecurity.DefinitionSourceFactoryBean">
<property name="resourceDetailsService" ref="resourceDetailsService" />
</bean>

<!-- 项目实现的URL-授权查询服务(第5步提供的ResourceDetailsServiceImpl.java类-->
<bean id="resourceDetailsService" class="com.security.ResourceDetailsServiceImpl" />

<!-- 授权判断配置, 将授权名称的默认前缀由ROLE_改为A_. -->
<bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.vote.RoleVoter">
<property name="rolePrefix" value="A_" />
</bean>
<bean class="org.springframework.security.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</beans>

到此为止,基本的java类,以及配置,都已完成。

第5步:准备测试jsp页面,login.jsp,具体如下:

<body>
    <CENTER>
    <h2>用户登陆-SpringSecurity安全配置Demo</h2>
   <form method="post" id="loginForm" class="login-form" action="/j_spring_security_check" >
    <div class="bg-login-error" <c:if test="${empty SPRING_SECURITY_LAST_EXCEPTION}">style='display:none;'</c:if>>
用户名或密码错误。
   </div>
      用户名:
<input id="j_username" type="text" tabindex="1"  name="j_username" value=""/><br/>
密     码:
<input id="j_password" type="password" tabindex="1"  name="j_password" value=""/><br/>
  <button type="submit">登 录</button>
  <button type="reset">重 置</button>
</form>
</CENTER>
  </body>

浏览器地址栏里输入下面的url:


测试:录入用户名:admin;密码:123456,然后点击提交按钮,最终页面如下:


测试:录入不存在的用户名:abcdfg;密码:123456,然后点击提交按钮,最终页面如下:


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值