`

spring security demo入门分析(转)

    博客分类:
  • java
 
阅读更多

要学习spring security 我个人的学习步骤是首先运行一个demo,让自己有个感性认识,上一篇文章已经介绍过了,在此就不介绍了。

 

然后分析demo工作包括哪些包,每个包什么作用,然后分析原理和验证流程,最后详细研究配置文件等内容。

 

下面就是对源码分析的过程。

 

spring security 包内容:

 

Core-spring-security-core.jar

包含了核心认证和权限控制类和接口, 提供核心的程序支持和最基本的API。是使用Spring Security所必须使用的。支持单独运行的应用, 提供远程客户端,方法(服务层)的安全和JDBC用户验证。包含顶级包:

  • org.springframework.security.core

  • org.springframework.security.access

  • org.springframework.security.authentication

  • org.springframework.security.provisioning

  • org.springframework.security.remoting

 

Web - spring-security-web.jar

包含过滤器和对应的web安全架构代码。在需要任何依赖servlet API的地方你将需要它。如果你需要Spring Security Web认证服务和基于URL的权限控制,请使用它。 他的主包是org.springframework.security.web

 

Config - spring-security-config.jar

包含安全命名控制解析代码(因此我们不能直接把它用在你的应用中)。 如果使用了Spring Security XML命名控制来进行配置的时候需要使用。它的主包是org.springframework.security.config

 

LDAP - spring-security-ldap.jar

LDAP认证和实现代码,如果你需要使用LDAP认证或管理LDAP用户实体就是必须的。 它的顶级包是org.springframework.security.ldap

 

ACL - spring-security-acl.jar

处理领域对象ACL实现。用来提供安全特定的领域对象实例,在你的应用中。它的 顶级包是org.springframework.security.acls

 

CAS - spring-security-cas-client.jar

Spring Security的CAs客户端集成。如果你希望使用Spring Security web认证 整合一个CAS单点登录服务器。它的顶级包是 org.springframework.security.cas

 

OpenID - spring-security-openid.jar

 

OpenID web认证支持。用来认证用户,通过一个外部的OpenID服务。 org.springframework.security.openid。需要OpenID4Java。

 

crypto  spring-security-crypto-3.1.0.RELEASE.jar

 

加密相关的包,它的顶级包是org.springframework.security.crypto

 

remoting  spring-security-remoting-3.1.0.RELEASE.jar

 

远程客户端相关的包,主要包括dns、rmi、httpinvoker。它的顶级包是org.springframework.security.remoting

 

taglibs spring-security-taglibs-3.1.0.RELEASE.jar

 

web标签相关的包,可以用在jsp或者模板中。它的顶级包是org.springframework.security.taglibs

 

demo说明

 

根据官方文档spring-security-samples-tutorial- 3.1.0.RELEASE.war是进行spring security的最基础的文档,于是就对这个工程进行了分析。引入了工程后,发现代码确实很少,jsp也很少就6个非常简单的jsp,然后通过 tomcat运行,效果也很简单。

 

运行后发现一个很奇怪的现象就是找不到登录页,下图就是默认的home页面。

 

点击Secure page后会进入登录页面,但是这个页面在代码里面是找不到的,为了这个问题,我研究了好一会才发现登录页面的位置。

 

 

 

 

登录页面位于:org.springframework.security.web.authentication.ui包的DefaultLoginPageGeneratingFilter.java类中。

 

由DefaultLoginPageGeneratingFilter过滤器动态生成的一个页面。

 

这时候我想到了一个问题,就是为什么,home页面没有让登录,点击Secure page页面让登录呢?后来找到了答案。

 

在web登录的所有资源都是是否需要权限验证是放在配置文件applicationContext-security.xml中的。

 

    <http use-expressions="true">

<!--下面两句表示在访问下面配置的资源的时候需要身份验证,如果没有身份验证跳转到登录页面-->
        <intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')"/>
        <intercept-url pattern="/secure/**" access="isAuthenticated()" />
        <intercept-url pattern="/**" access="permitAll" />

<!--下面一句表示登录页面的配置选项,默认登录页就是上面由DefaultLoginPageGeneratingFilter生成的页面

默认跳转地址为/j_spring_security_check-->
        <form-login />
        <logout logout-success-url="/loggedout.jsp" delete-cookies="JSESSIONID"/>
        <remember-me />
        <session-management invalid-session-url="/timeout.jsp">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
        </session-management>

    </http>

isAuthenticated()定义的位置如下:

spring-security-core.jar中定义的接口

 

public interface Authentication extends Principal, Serializable { 

 

     Collection<GrantedAuthority> getAuthorities(); 

 

    Object getCredentials(); 

 

     Object getDetails(); 

 

     Object getPrincipal(); 

 

     boolean isAuthenticated(); 

 

     void setAuthenticated(boolean isAuthenticated)throws IllegalArgumentException; 

 

 

 

 

登录页面配置例子:

 

<form-login login-page="/login.jsp"default-target-url="/index.jsp" always-use-default-target="true" authentication-failure-url="/login.jsp?error=1" /> 

 

备注:在自定义的登录页面中用户名的名字为j_username,密码为j_password,记住密码为_spring_security_remember_me,这些内容都是写死的,写错了没有办法进行验证。

 

 

 

默认的验证代码为:

 

在包org.springframework.security.web.authentication,UsernamePasswordAuthenticationFilter过滤器中

 

关键代码为:

 

  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { 

 

//注意这里只能用post提交。
        if (postOnly && !request.getMethod().equals("POST")) { 
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); 
        } 
 
        String username = obtainUsername(request); 
        String password = obtainPassword(request); 
 
        if (username == null) { 
            username = ""; 
        } 
 
        if (password == null) { 
            password = ""; 
        } 
 
        username = username.trim(); 
 
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); 
 
        // Place the last username attempted into HttpSession for views 
        HttpSession session = request.getSession(false); 
 
        if (session != null || getAllowSessionCreation()) { 
            request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username)); 
        } 
 
        // Allow subclasses to set the "details" property 
        setDetails(request, authRequest); 
 
        return this.getAuthenticationManager().authenticate(authRequest); 
    } 
 
用户信息的配置是放在配置文件applicationContext-security.xml中的,关键配置项为:

 

    <authentication-manager>
        <authentication-provider>
            <password-encoder ref="encoder"/>
            <user-service>
                <user name="rod" password="4efe081594ce25ee4efd9f7067f7f678a347bccf2de201f3adf2a3eb544850b465b4e51cdc3fcdde" authorities="supervisor, user, teller" />
                <user name="dianne" password="957ea522524a41cbfb649a3e293d56268f840fd5b661b499b07858bc020d6d223f912e3ab303b00f" authorities="user,teller" />
                <user name="scott" password="fb1f9e48058d30dc21c35ab4cf895e2a80f2f03fac549b51be637196dfb6b2b7276a89c65e38b7a1" authorities="user" />
                <user name="peter" password="e175750688deee19d7179d444bfaf92129f4eea8b4503d83eb8f92a7dd9cda5fbae73638c913e420" authorities="user" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

 

上面就是对demo的基本研究。

最后想说的就是框架其实只是用来快速开发用的,很多框架基本上都封装了实现的细节,我们 只知道怎么用是远远不够的,那样干的只是体力活,更多的我们应该去知道它为什么这么用,怎么实现的,然后我们可以不用框架,也可以写出很好的代码。其实说 白了,我们最需要掌握的就是解决问题的能里,能不是去跟别人说我会用什么什么框架之类的!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics