最近做了一个项目,权限管理部分用的是spring security。spring security 是基于spring AOP和servlet过滤器的安全框架。spring security 在web请求级和方法调用级处理身份确认和方法授权,在spring framework 基础上,spring security充分利用了依赖注入(DI,Dependency Injection)和面向切面技术。
spring security有自己的标签库,用起来挺方便的,推荐。
项目环境:
struts2.0
spring2.5.6
spring security2.0.5
hibernate3.3.2
applicationContext-spring-security.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"
default-lazy-init="true">
<http auto-config='true' access-denied-page="/access-denied.jsp">
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/imgage/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<intercept-url pattern="/common/**" filters="none" />
<intercept-url pattern="/login.jsp*" filters="none"/>
<intercept-url pattern="/jsp/report/**" access="ROLE_ADMIN,ROLE_AUDITOR"/>
<intercept-url pattern="/jsp/sysmgr/common-setting*" access="ROLE_ADMIN,ROLE_SYS_ADMIN"/>
<form-login login-page="/login.jsp" default-target-url="/login!login" always-use-default-target="true" />
</http>
<authentication-provider user-service-ref="userDetailsService">
<!-- 可设置hash使用sha1或md5散列密码后再存入数据库 -->
<password-encoder hash="md5" />
</authentication-provider>
<beans:bean id="userDetailsService"
class="cn.com.letour.fimascenter.action.sysmgr.LoginAction" >
</beans:bean>
<beans:bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:message_zh_CN"/>
</beans:bean>
</beans:beans>
web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>fimas</display-name>
<!-- spring配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext-*.xml,classpath:org/codehaus/xfire/spring/xfire.xml</param-value>
</context-param>
<!-- 数据库连接池配置文件 -->
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin.do</url-pattern>
</servlet-mapping>
<!-- xFire配置 -->
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>
org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<!-- svgPdf导出servlet -->
<servlet>
<servlet-name>SaveAnalysePDFServlet</servlet-name>
<servlet-class>cn.com.letour.fimascenter.base.servlet.SaveAnalysePDFServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>SaveStrateryPDFServlet</servlet-name>
<servlet-class>cn.com.letour.fimascenter.base.servlet.SaveStrateryPDFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SaveAnalysePDFServlet</servlet-name>
<url-pattern>/servlet/SaveAnalysePDFServlet.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SaveStrateryPDFServlet</servlet-name>
<url-pattern>/servlet/SaveStrateryPDFServlet.do</url-pattern>
</servlet-mapping>
<!-- 字符 filter -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 登录过滤器 -->
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>cn.com.letour.fimascenter.base.filter.LoginFilter</filter-class>
<init-param>
<param-name>userLoginFalse</param-name>
<param-value>/fimas/login.jsp</param-value>
</init-param>
</filter>
<!-- 过滤自定义servlet -->
<filter>
<filter-name>redisp</filter-name>
<filter-class>cn.com.letour.fimascenter.base.filter.ReDispatcherFilter</filter-class>
<init-param>
<param-name>includeServlets</param-name>
<param-value>fimasService</param-value>
</init-param>
</filter>
<!-- Hibernate Open Session In View filter-->
<filter>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<!-- SpringSecurity filter-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- sitemesh filter-->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<!--struts2配置 -->
<filter>
<filter-name>action2-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<!-- Filter 映射 -->
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>redisp</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>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>action2-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Spring的ApplicationContext 载入 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- -->
<listener>
<listener-class>cn.com.letour.fimascenter.base.listener.UserLoginListener</listener-class>
</listener>
<!-- log4j保存路径配置 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>webApp.root</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>600000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!--session失效 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- Welcome file lists -->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<!--
出错页面定义 <error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/common/500.jsp</location> </error-page> <error-page>
<error-code>500</error-code> <location>/common/500.jsp</location>
</error-page> <error-page> <error-code>404</error-code>
<location>/common/404.jsp</location> </error-page>
-->
</web-app>
实现security的UserDetailsService接口:
public class LoginAction extends ActionSupport implements UserDetailsService {
private static final long serialVersionUID = 1L;
/**************************************** 属性 ********************************/
private String j_username;
private String j_password;
private static User tempUser;
@Autowired
private UserInfoBiz userInfoBiz;
/**************************************** setget ****************************/
public String getJ_username() {
return j_username;
}
public void setJ_username(String j_username) {
this.j_username = j_username;
}
public String getJ_password() {
return j_password;
}
public void setJ_password(String j_password) {
this.j_password = j_password;
}
/**
* 用户登录
*/
public String login() {
UserInfo user = null;
String tempUsername = tempUser.getUsername();
// System.out.println("============>>"+temp);
user = userInfoBiz.findUserByLoginName(tempUsername);
ServletActionContext.getRequest().getSession(false);
Map<String, Object> map = ActionContext.getContext().getSession();
// 用户监听session类
UserLoginListener userLoginListener = new UserLoginListener();
// 登录用户信息
CurrentUser c = new CurrentUser();
c.setLoginName(user.getLoginName());
c.setUserInfoId(user.getUserInfoId());
c.setLoginIp(ServletActionContext.getRequest().getRemoteAddr());
c.setUserName(user.getUserName());
c.setRoleName(user.getUserRoles().iterator().next().getRoleInfo().getRoleName());
userLoginListener.setCurrentUser(c);
userLoginListener.setUserInfoBiz(userInfoBiz);
// 必须把登录监听类放入session中
map.put(Global.CURRENT_USER, userLoginListener);
// System.out.println(c.getRoleName());
if (null != c.getRoleName() && c.getRoleName().equals("ROLE_AUDITOR")) {
return "indexOfReport";
} else {
return "index";
}
}
/**
* 用户登出
*
* @return
*/
public String logout() {
try {
// 移除session
ActionContext.getContext().getSession().remove("currentUser");
// session失效
ActionContext.getContext().getSession().clear();
} catch (Exception e) {
e.printStackTrace();
}
return "login";
}
/**
* 获得登录用户信息.
*/
public User loadUserByUsername(String j_username) throws UsernameNotFoundException, DataAccessException {
UserInfo user = userInfoBiz.findUserByLoginName(j_username);
if (user == null) {
throw new UsernameNotFoundException("用户" + j_username + " 不存在");
}
GrantedAuthority[] grantedAuths = obtainGrantedAuthorities(user);
org.springframework.security.userdetails.User userDetail = new org.springframework.security.userdetails.User(
user.getLoginName(), user.getLoginPassword(), user.getEnabled(), true, true, true, grantedAuths);
tempUser = userDetail;
// String name = u.getUsername();
// String pass = u.getPassword();
// String role = (u.getAuthorities())[0].getAuthority();
return userDetail;
}
/**
* 获得用户所有角色的权限.
*/
private GrantedAuthority[] obtainGrantedAuthorities(UserInfo user) {
Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
for (UserRole role : user.getUserRoles()) {
authSet.add(new GrantedAuthorityImpl(role.getRoleInfo().getRoleName()));
}
return authSet.toArray(new GrantedAuthority[authSet.size()]);
}
}
登录页面login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<base></base>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>我的项目</title>
<link href="${ctx}/css/login.css" rel="stylesheet" />
<!--[if IE 6]>
<link rel="stylesheet" href="${ctx}/css/ie.css" type="text/css" />
<![endif]-->
<script type="text/javascript" src="${ctx}/js/jquery-1.4.2.min.js"></script>
</head>
<body>
<div class="body_div">
<div class="body_right">
<div class="logo"></div>
<div class="title"></div>
<form action="${ctx}/j_spring_security_check" method="post" id="form">
<div class="userType">
<label style="color:red;font-size: 14px;">${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}</label>
</div>
<div class="bg">
</div>
<div class="content">
<div class="user_div">
<div class="userInfo">账号:</div>
<div class="input_div">
<input type="text" name="j_username" id="j_username" value="" class="input"/>
</div>
</div>
<div class="password_div">
<div class="userInfo">密码:</div>
<div class="input_div">
<input type="password" name="j_password" id="j_password" value="" class="input" />
</div>
</div>
<div class="login">
<input type="submit" value="登录" />
</div>
</div>
</form>
</div>
</div>
</body>
</html>