源码
下载
文件结构

actions包定义了struts2 action。
action.results包定义了自己的struts result。此半成品用不到。
aspect包将定义aop切面。此半成品用不到。
auth包定义了用于SS认证的自定义类。我们将使用自己的类来查询数据库。
business包定义了各种service接口以及实现。
db.mapper包定义了Mybatis Dao接口。
model包定义了域模型。本文中域模型只有一个User类。
util包定义了工具类。本文util将提供password encode功能。
applicationContext-aop.xml本文不用。
applicationContext-business.xml配置service bean。
applicationContext-mybatis.xml配置Spring和Mybatis的集成以及各种Dao。
applicationContext-security.xml配置Spring Security。
applicationContext-struts.xml配置Spring与Struts的集成以及所有的struts bean。
schema.sql中定义了数据库表。
log4j与struts.xml不多说。
在jsp中,本文将用到login.jsp, register.jsp以及登陆成功后可以访问到test.jsp。其它的不会用到。
在resources下面,/com/xpbug/demo/db/mybatis-config.xml定义了mybatis。
在resources下面,/com/xpbug/demo/db/mapper/UserDao.xml定义了UserDao的实现。
开发平台选用的是Eclipse+Maven+tomcat. 项目的依赖请查看pom.xml。
配置web.xml
将Spring Security filter至于struts filter之前,让SS可以多所有的URL进行保护。
springSecurityFilterChain
/*
struts2
/user/*
/auth/*
/register/*
配置Spring Security
让SS对/auth/login*和/register/**放行。配置Authentication-Provider使用自己定义的UserService, 并使用PasswordEncoder对password进行加密。
default-target-url="/user/profile" login-processing-url="/spring_security_check"
authentication-failure-url="/auth/login?error" password-parameter="password" username-parameter="username" />
其中UserDao在applicationContext-mybatis.xml中有定义。
com.xpbug.demo.auth.UserService的实现为:
public class UserService implements UserDetailsService {
private UserDao userDao;
private Logger logger = LoggerFactory.getLogger(UserService.class);
/* (non-Javadoc)
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
com.xpbug.demo.model.User user = this.userDao.getLoginById(username);
List roles = user.getRoles();
List authorities = new ArrayList();
for (String r:roles) {
logger.info("Grant role: {}", r);
authorities.add(new SimpleGrantedAuthority(r));
}
User sUser = new User(user.getUserId(), user.getPassword(), authorities);
return sUser;
}
// Getters and Setters...
}
在UserService中,我们使用UserDao获取数据库中的用户,然后将数据库取出的用户,封装成SS所需要的形式。
这样,登录部分完成了。接下来,我们来定义Struts的Action。
Struts
在Struts中,我将定义以下几个URI:
/auth/login 展示登录页面
/auth/logout 注销,然后转登录页面。
/register/form 展示注册页面
/register/do 处理register form POST。然后chain to auto login action.
/register/autoLogin 承接/register/do, 进行自动登录,成功以后重定向到/user/profile
/user/profile 一个受SS保护的页面。
struts.xml:
/WEB-INF/jsp/login.jsp
/spring_logout
/WEB-INF/jsp/register.jsp
autoLogin
login
/user/profile
/WEB-INF/jsp/test.jsp
其它Action不表,重点说下掌管注册和自动登录的两个Action。
RegisterAction
服务于注册的Action需要接收用户id和密码。此外,它还需要userService服务于用户创建,util服务于encode password。util的定义可以在applicationContext-business.xml中找到,它使用了Spring Security提供的password encoder,和登录时使用的encoder是同一个bean。
用户创建成功以后,将使用Chain Result,转到AutoLoginAction。
public class RegisterAction extends ActionSupport {
private static final long serialVersionUID = -3114254552070420296L;
private UserService userService;
private Util util;
private String uid;
private String password;
private String repassword;
public String register() {
if (password.equals(repassword)) {
User user = new User();
user.setUserId(uid);
user.setPassword(util.encodePassword(password));
userService.registerUser(user);
}
return "success";
}
// Getters and Setters...
}
AutoLoginAction
因为AutoLoginAction是由RegisterAction的result Chain过来的,所以可以接收RegisterAction相同的parameters。我们让它接收uid和password两个参数。
此外,它还需要用到登录时使用的AuthenticationManager, AuthenticationManager将会被Spring注入。
在login函数执行完毕以后,Session中就存在了SS所需要的所有认证信息。后面的URL就不需要再进行认证了。
AutoLoginAction成功以后,会重定向到/user/profile页面。
public class AutoLoginAction {
private String uid;
private String password;
private AuthenticationManager authenticationManager;
public String login() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uid, password);
HttpServletRequest request = ServletActionContext.getRequest();
// generate session if one doesn't exist
request.getSession();
token.setDetails(new WebAuthenticationDetails(request));
Authentication authenticatedUser = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
return "success";
}
// Getters and Setters ...
}
Bean注册
关于Struts, mybatis和business各类bean的注册,不多废话。可以查看源代码。
运行
请先安装mysql,然后使用schema.sql创建数据库。
在applicationContext-mybatis.xml中修改datasource的配置。
编译打包成demo.war. 直接部署到tomcat中。