Spring Security4的配置,以及一些吐槽.(一)

我有一本参考书,是<<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>


在看dispatcher-servlet.xml

<?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 onload='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>

好了,又可以开始新一轮的测试了.

第三步 使用数据库来代替内存存储.

下一篇文章在写.






展开阅读全文

没有更多推荐了,返回首页