Spring Security+Struts2实现登录,注册,以及注册自动登录模块
博客专区 > xpbug 的博客 > 博客详情
Spring Security+Struts2实现登录,注册,以及注册自动登录模块
xpbug 发表于3年前
Spring Security+Struts2实现登录,注册,以及注册自动登录模块
  • 发表于 3年前
  • 阅读 964
  • 收藏 3
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 最近正在编写用户管理模块。此模块将使用Spring Security, Spring, Struts2, Tiles和Mybatis集成实现。将来,我会为此写一篇博文,但在之前,我想先把这几天的半成品记录并共享一下。这个半成品已经集成了SS3,Struts2和Mybatis。它实现的功能只是登录,注册,以及注册后自动登录。 这篇文章主要讲述如何自定义SS的用户服务模块,以及如何实现注册和自动登录。并不介绍SSH或者SSM的集成,此部分将在所有模块完成以后另写一篇文章。到时还会共享所有的代码。当然在本文中,我也会共享目前的半成品代码。

源码

下载

半成品源码下载地址: http://pan.baidu.com/s/1bn91N6B 

文件结构

  1. actions包定义了struts2 action。

  2. action.results包定义了自己的struts result。此半成品用不到。

  3. aspect包将定义aop切面。此半成品用不到。

  4. auth包定义了用于SS认证的自定义类。我们将使用自己的类来查询数据库。

  5. business包定义了各种service接口以及实现。

  6. db.mapper包定义了Mybatis Dao接口。

  7. model包定义了域模型。本文中域模型只有一个User类。

  8. util包定义了工具类。本文util将提供password encode功能。

  9. applicationContext-aop.xml本文不用。

  10. applicationContext-business.xml配置service bean。

  11. applicationContext-mybatis.xml配置Spring和Mybatis的集成以及各种Dao。

  12. applicationContext-security.xml配置Spring Security。

  13. applicationContext-struts.xml配置Spring与Struts的集成以及所有的struts bean。

  14. schema.sql中定义了数据库表。

  15. log4j与struts.xml不多说。

  16. 在jsp中,本文将用到login.jsp, register.jsp以及登陆成功后可以访问到test.jsp。其它的不会用到。

  17. 在resources下面,/com/xpbug/demo/db/mybatis-config.xml定义了mybatis。

  18. 在resources下面,/com/xpbug/demo/db/mapper/UserDao.xml定义了UserDao的实现。

开发平台选用的是Eclipse+Maven+tomcat. 项目的依赖请查看pom.xml。

配置web.xml

将Spring Security filter至于struts filter之前,让SS可以多所有的URL进行保护。

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/user/*</url-pattern>
        <url-pattern>/auth/*</url-pattern>
        <url-pattern>/register/*</url-pattern>
    </filter-mapping>

配置Spring Security

让SS对/auth/login*和/register/**放行。配置Authentication-Provider使用自己定义的UserService, 并使用PasswordEncoder对password进行加密。

    <s:http use-expressions="true" authentication-manager-ref="AuthManager">
        <s:intercept-url pattern="/auth/login*" access="permitAll()" />
        <s:intercept-url pattern="/register/**" access="permitAll()" />
        <s:intercept-url pattern="/**" access="isAuthenticated()" />
        
        <s:form-login login-page='/auth/login'
            default-target-url="/user/profile" login-processing-url="/spring_security_check"
            authentication-failure-url="/auth/login?error" password-parameter="password" username-parameter="username" />

        <s:logout invalidate-session="true" logout-success-url="/auth/login?logout" logout-url="/spring_logout" />
    </s:http>

    <s:authentication-manager id="AuthManager">
        <s:authentication-provider ref="daoAuthProvider">
        </s:authentication-provider>
    </s:authentication-manager>

    <bean id="daoAuthProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="myUserAuthService" /> <!-- From business. We implement it. -->
        <property name="passwordEncoder" ref="passwordEncoder" />
    </bean>

    <bean id="myUserAuthService" class="com.xpbug.demo.auth.UserService">
        <!-- Use mybatis dao -->
        <property name="userDao" ref="UserDao"></property>
    </bean>

    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <constructor-arg name="strength" value="10"></constructor-arg>
    </bean>

其中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<String> roles = user.getRoles();
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
            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:

  1. /auth/login  展示登录页面

  2. /auth/logout  注销,然后转登录页面。

  3. /register/form  展示注册页面

  4. /register/do  处理register form POST。然后chain to auto login action.

  5. /register/autoLogin  承接/register/do, 进行自动登录,成功以后重定向到/user/profile

  6. /user/profile  一个受SS保护的页面。

struts.xml:

    <constant name="struts.action.extension" value="" />
	
    <package name="auth" extends="abstract" namespace="/auth">
        <action name="login" class="LoginPageAction">
            <result name="success">/WEB-INF/jsp/login.jsp</result>
        </action>
        <action name="logout">
            <result name="success" type="redirect">/spring_logout</result>
        </action>
    </package>
    
    <package name="register" extends="abstract" namespace="/register">
        <action name="form" class="RegisterAction">
            <result>/WEB-INF/jsp/register.jsp</result>
        </action>
        <action name="do" class="RegisterAction" method="register">
            <result name="success" type="chain">
                <param name="actionName">autoLogin</param>
                <param name="method">login</param>
            </result>
        </action>
        <action name="autoLogin" class="AutoLoginAction" method="login">
            <result type="redirect">/user/profile</result>
        </action>
    </package>
	
    <package name="user" extends="abstract" namespace="/user">
        <action name="profile">
            <result name="success">/WEB-INF/jsp/test.jsp</result>
        </action>
    </package>

其它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中。

可访问URL: http://localhost:8080/demo/auth/login 

共有 人打赏支持
粉丝 298
博文 97
码字总数 125336
×
xpbug
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: