Spring Security Reference 部分翻译

来源:互联网 发布:java后端需要学什么 编辑:程序博客网 时间:2024/05/16 19:13

本文为个人学习spring security 是对官方技术文档的个人翻译,以便学习使用。原文链接http://docs.spring.io/spring-security/site/docs/4.1.2.BUILD-SNAPSHOT/reference/htmlsingle/#samples


5. Java Configuration(java配置文件)

在Spring3.1版本的时候就支持使用java配置文件的方式。从Spring Security 3.2开始 就可以用配置的方式轻松的配置Spring Security到项目中而不需要使用xml 的方式。

General support for Java Configuration was added to Spring framework in Spring 3.1. Since Spring Security 3.2 there has been Spring Security Java Configuration support which enables users to easily configure Spring Security without the use of any XML.

如果你对第6章使用安全空间方式配置,那么你应该可以很轻松的找到他们之间的很多相似之处。

If you are familiar with the Chapter 6, Security Namespace Configuration then you should find quite a few similarities between it and the Security Java Configuration support.

Spring Security 提供了很多简单的以jc结尾的使用Spring Security java配置的说明。

Spring Security provides lots of sample applications that end in -jc which demonstrate the use of Spring Security Java Configuration.

5.1 Hello Web Security Java Configuration

第一步就创建我们的Spring Security java配置文件。这个配置文件就是一个springSecurityFilterChain的Servlet Filter ,他将会负责我们项目的所有安全问题(包括保护程序url,验证登录用户名和密码,重定向到登录的形式等等)你可以在下面找到最基本的配置例子:
The first step is to create our Spring Security Java Configuration. The configuration creates a Servlet Filter known as the springSecurityFilterChain which is responsible for all the security (protecting the application URLs, validating submitted username and passwords, redirecting to the log in form, etc) within your application. You can find the most basic example of a Spring Security Java Configuration below:

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.*;import org.springframework.security.config.annotation.authentication.builders.*;import org.springframework.security.config.annotation.web.configuration.*;@EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");}}

这个方法的名字‘configureGlobal ’ 并不重要,但是重要的是他的类以注解(@EnableWebSecurity@EnableGlobalMethodSecurity, or @EnableGlobalAuthentication.)的方式配置了 AuthenticationManagerBuilder类。否则会有不可预测的结果。

The name of the configureGlobal method is not important. However, it is important to only configure AuthenticationManagerBuilder in a class annotated with either @EnableWebSecurity@EnableGlobalMethodSecurity, or @EnableGlobalAuthentication.Doing otherwise has unpredictable results.

这个配置文件并不多,但是他做了很多的事:

There really isn’t much to this configuration, but it does a lot. You can find a summary of the features below:

  • 对程序中的每一个URL进行验证。
  • Require authentication to every URL in your application
  • 为你生成一个登陆界面
  • Generate a login form for you
  • 允许以用户名为user和密码为password的基于报单方式的验证。
  • Allow the user with the Username user and the Password password to authenticate with form based authentication
  • 允许用户注销
  • Allow the user to logout
  • CSRF攻击防范
  • CSRF attack prevention
  • 会话固定保护
  • Session Fixation protection
  • 安全头一体化
  • Security Header integration

    • HTTP Strict Transport Security for secure requests
    • X-Content-Type-Options integration
    • Cache Control (can be overridden later by your application to allow caching of your static resources)
    • X-XSS-Protection integration
    • X-Frame-Options integration to help prevent Clickjacking
  • Integrate with the following Servlet API methods

    • HttpServletRequest#getRemoteUser()
    • HttpServletRequest.html#getUserPrincipal()
    • HttpServletRequest.html#isUserInRole(java.lang.String)
    • HttpServletRequest.html#login(java.lang.String, java.lang.String)
    • HttpServletRequest.html#logout()

5.1.1 AbstractSecurityWebApplicationInitializer

如果你并没有使用Spring 或者Spring MVC,你需要确定WebSecurityConfig的父类已经加载了它。你可以通过下面的例子看到:

If you are not using Spring or Spring MVC, you will need to pass in the WebSecurityConfig into the superclass to ensure the configuration is picked up. You can find an example below:

import org.springframework.security.web.context.*;public class SecurityWebApplicationInitializerextends AbstractSecurityWebApplicationInitializer {public SecurityWebApplicationInitializer() {super(WebSecurityConfig.class);}}

这个SecurityWebApplicationInitializer的类做了一下的几个工作:

The SecurityWebApplicationInitializer will do the following things:

  • 自动为你的程序里的每一个URL注册 springSecurityFilterChain Filter
  • Automatically register the springSecurityFilterChain Filter for every URL in your application
  • 加载 WebSecurityConfig时添加ContextLoaderListener 
  • Add a ContextLoaderListener that loads the WebSecurityConfig.

5.1.3 AbstractSecurityWebApplicationInitializer with Spring MVC

如果我们使用Spring,可能在我们应用程序的其他地方已经加载了一个spring 的配置文件。如果我们使用以前的配置,我们可能会得到错误。因此我们应该使用已经存在的Spring配置配置我们的spring Security。例如,我们使用了spring MVC 我们的SecurityWebApplicationInitializer就应该看下面的例子:
If we were using Spring elsewhere in our application we probably already had a WebApplicationInitializer that is loading our Spring Configuration. If we use the previous configuration we would get an error. Instead, we should register Spring Security with the existing ApplicationContext. For example, if we were using Spring MVC our SecurityWebApplicationInitializer would look something like the following:

import org.springframework.security.web.context.*;public class SecurityWebApplicationInitializerextends AbstractSecurityWebApplicationInitializer {}

这个仅仅是为我们应用程序的每一个URL注册到springSecurityFilterChain Filter。之后我们要确定WebSecurityConfig已经加载到了我们已经存在的应用程序中。例如我们使用SpringMVC 它将会在getRootConfigClasses()中加入。

This would simply only register the springSecurityFilterChain Filter for every URL in your application. After that we would ensure that WebSecurityConfig was loaded in our existing ApplicationInitializer. For example, if we were using Spring MVC it would be added in the getRootConfigClasses()

public class MvcWebApplicationInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[] { WebSecurityConfig.class };}// ... other overrides ...}

5.2 HttpSecurity

到目前为止我们的WebSecurityConfig只包含了如何去验证我们的用户。那Spring security是怎么知道我们想要要求所有人进行验证。他又是怎么知道我们想要通过基于安全提供的验证。这是因为WebSecurityConfigurerAdapter在configure(HttpSecurity http中提供了很多默认的方法,比如:
Thus far our WebSecurityConfig only contains information about how to authenticate our users. How does Spring Security know that we want to require all users to be authenticated? How does Spring Security know we want to support form based authentication? The reason for this is that the WebSecurityConfigurerAdapterprovides a default configuration in the configure(HttpSecurity http) method that looks like:
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();}

上面的默认配置:
确保对我们的应用程序的任何请求都要求用户进行身份验证
允许用户以form 为基础的登录进行身份验证
允许用户验证的HTTP基本认证

The default configuration above:

  • Ensures that any request to our application requires the user to be authenticated
  • Allows users to authenticate with form based login
  • Allows users to authenticate with HTTP Basic authentication
你会发现,这个配置文件和xml命名空间非常像
You will notice that this configuration is quite similar the XML Namespace configuration:
<http><intercept-url pattern="/**" access="authenticated"/><form-login /><http-basic /></http>
这个java配置文件使用and()的作用等效于xml中的结束标签,他允许我们继续添加根标签,如果你阅读代码也可以理解,我想要配置授权请求和配置形式登录和配置HTTP基本认证。
The Java Configuration equivalent of closing an XML tag is expressed using the and() method which allows us to continue configuring the parent. If you read the code it also makes sense. I want to configure authorized requests and configure form login and configure HTTP Basic authentication.
However, Java Configuration has different defaults URLs and parameters. Keep this in mind when creating custom login pages. The result is that our URLs are more RESTful. Additionally, it is not quite so obvious we are using Spring Security which helps to prevent information leaks. For example:

5.3 Java Configuration and Form Login

当你被要求登录的时候,你可能想知道登录页面从哪里来,因为我们没有提到任何的HTML或者jsp页面。由于Spring Security的默认配置没有显式设置的登录页面的网址。这是由于Spring Security 有一个自动生成的功能,并使用标准值的网址处理提交的登录,登录后用户将被发送到默认的目标网址。
You might be wondering where the login form came from when you were prompted to log in, since we made no mention of any HTML files or JSPs. Since Spring Security’s default configuration does not explicitly set a URL for the login page, Spring Security generates one automatically, based on the features that are enabled and using standard values for the URL which processes the submitted login, the default target URL the user will be sent to after logging in and so on.
虽然可以自动快速的布置登录界面并运行,但是大部分的项目都希望在页面布置我们自己的登录页面,所以我们可以按下面的方法更新:
While the automatically generated log in page is convenient to get up and running quickly, most applications will want to provide their own log in page. To do so we can update our configuration as seen below:
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login") 1.permitAll();        2}

1

The updated configuration specifies the location of the log in page.更新配置指定了登录界面

2

We must grant all users (i.e. unauthenticated users) access to our log in page. The formLogin().permitAll() method allows granting access to all users for all URLs associated with form based log in.

我们必须为那些想要访问登录界面的所有用户放行。
下面是一个我们自己配置的以jsp页面写成的登录页面:
An example log in page implemented with JSPs for our current configuration can be seen below:
在下面我们配置的这个登录界面中,我们可以轻松的修改一下默认的配置
The login page below represents our current configuration. We could easily update our configuration if some of the defaults do not meet our needs.
<c:url value="/login" var="loginUrl"/><form action="${loginUrl}" method="post">       1<c:if test="${param.error != null}">        2<p>Invalid username and password.</p></c:if><c:if test="${param.logout != null}">       3<p>You have been logged out.</p></c:if><p><label for="username">Username</label><input type="text" id="username" name="username"/>4</p><p><label for="password">Password</label><input type="password" id="password" name="password"/>5</p><input type="hidden"                        6name="${_csrf.parameterName}"value="${_csrf.token}"/><button type="submit" class="btn">Log in</button></form>

1

A POST to the /login URL will attempt to authenticate the user

2

If the query parameter error exists, authentication was attempted and failed

3

If the query parameter logout exists, the user was successfully logged out

4

The username must be present as the HTTP parameter named username

5

The password must be present as the HTTP parameter named password

6

We must Section 18.4.3, “Include the CSRF Token” To learn more read the Chapter 18, Cross Site Request Forgery (CSRF) section of the reference

5.4 Authorize Requests 请求授权

我们的例子中只是为每一个URL添加了登录认证,我们可以用http.authorizeRequests()方法添加更多的子标签方法
Our examples have only required users to be authenticated and have done so for every URL in our application. We can specify custom requirements for our URLs by adding multiple children to our http.authorizeRequests() method. For example:
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()                                                                1.antMatchers("/resources/**", "/signup", "/about").permitAll()                  2.antMatchers("/admin/**").hasRole("ADMIN")                                      3.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")            4.anyRequest().authenticated()                                                   5.and()// ....formLogin();}

1

There are multiple children to the http.authorizeRequests() method each matcher is considered in the order they were declared.   在http.authorizeRequests()方法中有多个子标签,并已他们声明的顺序进行匹配

2

We specified multiple URL patterns that any user can access. Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".

我们指定了多个用户可以访问的URL,具体来说就以 "/resources/", equals "/signup", or equals "/about"开头的访问

3

Any URL that starts with "/admin/" will be resticted to users who have the role "ROLE_ADMIN". You will notice that since we are invoking the hasRole method we do not need to specify the "ROLE_" prefix.

任何访问/admin/ 的URL都必须具有ADMIN的角色,你可以看到因为我们使用了hasRole()方法,所以我们不用添加“ROLE_”前缀。

4

Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA". You will notice that since we are using the hasRole expression we do not need to specify the "ROLE_" prefix.

5

Any URL that has not already been matched on only requires that the user be authenticated

没有匹配的其他网址只需要进行用户验证

5.5 Handling Logouts

When using the WebSecurityConfigurerAdapter, logout capabilities are automatically applied. The default is that accessing the URL /logout will log the user out by:

当我们使用自动应用的websecurityconfigureradapter注销功能时,默认会链接到将会使我们登出的URL页面,登出的布置如下
  • Invalidating the HTTP Session
  • Cleaning up any RememberMe authentication that was configured
  • Clearing the SecurityContextHolder
  • Redirect to /login?logout
使HTTP会话失效
清理任何配置记得认证
清理securitycontextholder
重定向到/登录?注销
Similar to configuring login capabilities, however, you also have various options to further customize your logout requirements:
和登录功能类似,你也可以配置你各种各样的登出功能
protected void configure(HttpSecurity http) throws Exception {http.logout()                                                                1.logoutUrl("/my/logout")                                                 2.logoutSuccessUrl("/my/index")                                           3.logoutSuccessHandler(logoutSuccessHandler)                              4.invalidateHttpSession(true)                                             5.addLogoutHandler(logoutHandler)                                         6.deleteCookies(cookieNamesToClear)                                       7.and()...}

1

Provides logout support. This is automatically applied when using WebSecurityConfigurerAdapter.

提供注销的支持

2

The URL that triggers log out to occur (default is /logout). If CSRF protection is enabled (default), then the request must also be a POST. For for information, please consult the JavaDoc.

该URL指向注销页面(默认为/logout页面),默认提供CSRF保护功能,但必须是POST方法,获取更多信息请查询文档。

3

The URL to redirect to after logout has occurred. The default is /login?logout. For for information, please consult the JavaDoc.

注销成功后指向的页面

4

Let’s you specify a custom LogoutSuccessHandler. If this is specified, logoutSuccessUrl() is ignored. For for information, please consult the JavaDoc.


5

Specify whether to invalidate the HttpSession at the time of logout. This is true by default. Configures the SecurityContextLogoutHandler under the covers. For for information, please consult the JavaDoc

是否注销session,默认是.

6

Adds a LogoutHandlerSecurityContextLogoutHandler is added as the last LogoutHandler by default.

7

Allows specifying the names of cookies to be removed on logout success. This is a shortcut for adding a CookieClearingLogoutHandler explicitly.

Logouts can of course also be configured using the XML Namespace notation. Please see the documentation for the logout element in the Spring Security XML Namespace section for further details.
注销也可以用xml配置的方式,详情可以看Spring xml配置方面。
Generally, in order to customize logout functionality, you can add LogoutHandler and/or LogoutSuccessHandler implementations. For many common scenarios, these handlers are applied under the covers when using the fluent API.
一般来说,为了定制你的注销方法,可以添加logoutHandler或者logoutSuccessHandler方法实现。对于很对情况这些方法会在使用fluent时覆盖。

5.5.1 LogoutHandler

Generally, LogoutHandler implementations indicate classes that are able to participate in logout handling. They are expected to be invoked to perform necessary cleanup. As such they should not throw exceptions. Various implementations are provided:
一般来说,logouthandler实现表明,能够参与注销处理类。他们预计将被调用来执行必要的清理。因此,他们不会抛出异常。提供各种实现:
  • PersistentTokenBasedRememberMeServices
  • TokenBasedRememberMeServices
  • CookieClearingLogoutHandler
  • CsrfLogoutHandler
  • SecurityContextLogoutHandler
Instead of providing LogoutHandler implementations directly, the fluent API also provides shortcuts that provide the respective LogoutHandler implementations under the covers. E.g. deleteCookies() allows specifying the names of one or more cookies to be removed on logout success. This is a shortcut compared to adding aCookieClearingLogoutHandler.

5.5.2 LogoutSuccessHandler

The LogoutSuccessHandler is called after a successful logout by the LogoutFilter, to handle e.g. redirection or forwarding to the appropriate destination. Note that the interface is almost the same as the LogoutHandler but may raise an exception.

The following implementations are provided:

  • SimpleUrlLogoutSuccessHandler
  • HttpStatusReturningLogoutSuccessHandler

As mentioned above, you don’t need to specify the SimpleUrlLogoutSuccessHandler directly. Instead, the fluent API provides a shortcut by setting thelogoutSuccessUrl(). This will setup the SimpleUrlLogoutSuccessHandler under the covers. The provided URL will be redirected to after a logout has occurred. The default is /login?logout.

The HttpStatusReturningLogoutSuccessHandler can be interesting in REST API type scenarios. Instead of redirecting to a URL upon the successful logout, thisLogoutSuccessHandler allows you to provide a plain HTTP status code to be returned. If not configured a status code 200 will be returned by default.

5.5.3 Further Logout-Related References

  • Logout Handling
  • Testing Logout
  • HttpServletRequest.logout()
  • Section 17.4, “Remember-Me Interfaces and Implementations”
  • Logging Out in section CSRF Caveats
  • Section Single Logout (CAS protocol)
  • Documentation for the logout element in the Spring Security XML Namespace section

5.6 Authentication

Thus far we have only taken a look at the most basic authentication configuration. Let’s take a look at a few slightly more advanced options for configuring authentication.
到目前为止,我们只看了最基本的身份验证配置。让我们看看几个稍微更高级的配置身份验证的选项。

5.6.1 In Memory Authentication

We have already seen an example of configuring in memory authentication for a single user. Below is an example to configure multiple users:
我们已经看到了一个在内存中为单个用户配置的示例。下面是配置多个用户的一个例子:
@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles("USER", "ADMIN");}

5.6.2 JDBC Authentication

You can find the updates to suppport JDBC based authentication. The example below assumes that you have already defined a DataSource within your application. Thejdbc-javaconfig sample provides a complete example of using JDBC based authentication.
你可以找到支持基于JDBC的认证更新。下面的示例假定您已经在您的应用程序定义的数据源。JDBC javaconfig样本提供了一个完整的使用基于JDBC的实例验证。
@Autowiredprivate DataSource dataSource;@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.jdbcAuthentication().dataSource(dataSource).withDefaultSchema().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles("USER", "ADMIN");}

5.6.3 LDAP Authentication

You can find the updates to suppport LDAP based authentication. The ldap-javaconfig sample provides a complete example of using LDAP based authentication.

你可以找到支持的基于LDAP的认证更新。LDAP javaconfig示例提供了一个完整的例子使用的基于LDAP的认证。
@Autowiredprivate DataSource dataSource;@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.ldapAuthentication().userDnPatterns("uid={0},ou=people").groupSearchBase("ou=groups");}

The example above uses the following LDIF and an embedded Apache DS LDAP instance
上面的示例使用下面的LDIF和嵌入式Apache DS LDAP实例
users.ldif. 
dn: ou=groups,dc=springframework,dc=orgobjectclass: topobjectclass: organizationalUnitou: groupsdn: ou=people,dc=springframework,dc=orgobjectclass: topobjectclass: organizationalUnitou: peopledn: uid=admin,ou=people,dc=springframework,dc=orgobjectclass: topobjectclass: personobjectclass: organizationalPersonobjectclass: inetOrgPersoncn: Rod Johnsonsn: Johnsonuid: adminuserPassword: passworddn: uid=user,ou=people,dc=springframework,dc=orgobjectclass: topobjectclass: personobjectclass: organizationalPersonobjectclass: inetOrgPersoncn: Dianne Emusn: Emuuid: useruserPassword: passworddn: cn=user,ou=groups,dc=springframework,dc=orgobjectclass: topobjectclass: groupOfNamescn: useruniqueMember: uid=admin,ou=people,dc=springframework,dc=orguniqueMember: uid=user,ou=people,dc=springframework,dc=orgdn: cn=admin,ou=groups,dc=springframework,dc=orgobjectclass: topobjectclass: groupOfNamescn: adminuniqueMember: uid=admin,ou=people,dc=springframework,dc=org

0 0
原创粉丝点击