我有一本参考书,是<<Spring 实战>>第四版,虽然是一本关于实战的书,但是作者鼓励开发者采用注解的形式去做配置,
我一开始也是觉得很酷,毕竟0配置,对于我们来说是一种挑战,也是一种冲刺吧.但在实际配置中,却有很多的坑需要踩,
踩得你怀疑人生,书上说的东西虽然大多数在3.2以上就得到了实现,但是并不是所有类实际在3.2以上就得到了支持,
采用纯注解的配置简直就是在跟自己过不去,有这个时间,我都可以多看几章书去了.我写这么多,只是为了告诫自己,不要因为cool.
去做一些无意义的事情,大型企业开发使用全注解的少之又少,所以,以后还是加紧做正事.
以后尽量使用混合配置.
第一步,让我们先让安全权限认证跑起来.
先看一下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>springsecurity</display-name>
<!-- spring context -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
classpath:applicationContext-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring字符编码过滤器 -->
<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-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring security配置 -->
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>springSecurityFilterChain</param-value>
</init-param>
</filter>
<!-- 这里有一个细节,url-pattern spring security 配置的是 /*
而dispatcher 配置的是 / -->
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher-servlet.xml</param-value>
</init-param>
<!-- 启动级别,越低越早. -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd ">
<context:component-scan base-package="com.itheima.web"></context:component-scan>
<!-- Json视图解析 -->
<bean name="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="encoding">
<value type="org.codehaus.jackson.JsonEncoding">UTF8</value>
</property>
<property name="extractValueFromSingleKeyModel" value="true"></property>
<property name="contentType" value="application/json;charset=UTF-8" />
</bean>
<!-- 多视图解析 .json .xml -->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<!-- 用于开启 /userinfo/123?format=json 的支持 默认是true -->
<property name="favorParameter" value="false" />
<!-- 用于关闭 /userinfo/123.json 的支持 默认是true -->
<property name="favorPathExtension" value="true" />
<!-- 设置为true以忽略对Accept Header的支持 -->
<property name="ignoreAcceptHeader" value="true" />
<!-- 在没有扩展名时即: "/user/1" 时的默认展现形式 -->
<property name="defaultContentType" value="text/html" />
<!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<ref bean="jsonView" />
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- JSP如果使用了jstl 需要加 viewclass -->
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
<property name="exposeContextBeansAsAttributes" value="true"></property>
</bean>
</beans>
Internal的视图解析器要放在最后面.
applicationContext 只有一些测试用的数据.就不做展示了.
applicationContext-security
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 相当于WebSecurityConfigurerAdapter中对应的方法. -->
<!-- anto-config 为true将启用自动注册登录表单,基本身份验证,注销的URL,注销服务 -->
<!-- protected void configure(HttpSecurity http) 用于配置路径以及全选. -->
<http auto-config="true">
<!-- 拦截所有的url access 调用一个函数, true为通过,false为拒绝. 这里是要求有ROLE_USER角色 -->
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>
<!-- 相当于 protected void configure(AuthenticationManagerBuilder auth) 主要配置使用什么来进行连接. -->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<!-- 使用内存用户存储提供认证 -->
<user authorities="ROLE_USER" name="guest" password="guest" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
好了,现在项目已经可以跑起来了,输入任意连接都会跳转到,如下界面.
这个界面不是重点,我们需要了解的是,它提交到了那里.看一个form的提交地址提供到了项目的/login下.
第二步 然后,我们来自定义登陆界面.
修改applicationContext-security.xml配置
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 相当于WebSecurityConfigurerAdapter中对应的方法. -->
<!--
不能使用 <http pattern="/login" security="none" /> 这种格式,
因为这种形式,Spring Security 是不会使用csrf的.
-->
<!-- anto-config 为true将启用自动注册登录表单,基本身份验证,注销的URL,注销服务 -->
<!-- protected void configure(HttpSecurity http) 用于配置路径以及全选. -->
<!-- use-expressions = "true" 是开启access表达式 -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="hasRole('ANONYMOUS')" />
<!-- 拦截所有的url access 调用一个函数, true为通过,false为拒绝. 这里是要求有ROLE_USER角色 -->
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<!--
login-page 登陆界面
authentication-failure-url 登陆出错返回的地址
default-target-url 默认跳转的目标位置.
-->
<form-login login-page="/login" authentication-failure-url="/login?error=1" default-target-url="/index.jsp" />
</http>
<!-- 相当于 protected void configure(AuthenticationManagerBuilder auth) 主要配置使用什么来进行连接. -->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<!-- 使用内存用户存储提供认证 -->
<user authorities="ROLE_USER" name="guest" password="guest" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
login这个请求时LoginController类定义的.
@Controller
public class LoginController {
//注意一定要定义method 为get,不然post请求也会拦截,就会导致认证不了.
@RequestMapping(value="/login", method=RequestMethod.GET)
public String login(){
return "login";
}
}
返回的login最后会构成的路径是/WEB-INF/page/login.jsp界面.主体内容如下
<body οnlοad='document.loginForm.username.focus();'>
<div id="login-box">
<h2>请输入您的用户名与密码</h2>
<form name='loginForm' action="/springsecurity/login" method='POST'>
<table>
<tr>
<td>用户:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>密码:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="登录" /></td>
</tr>
<input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</table>
</form>
</div>
</body>
好了,又可以开始新一轮的测试了.
第三步 使用数据库来代替内存存储.
下一篇文章在写.