SpringSecurity安全框架
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
- “认证”,是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在你系 统中执行动作的其他系统。
- “授权”,指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证过程建立了。
安全框架入门
一、引入依赖
<!--引入安全框架web层的内容-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!--引入安全框架的配置文件 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!--引入安全框架的标签库-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
二、安全框架配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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
">
<!--认证-->
<!--
配置拦截的规则
auto-config="使用自带的页面"
use-expressions="是否使用spel表达式",如果使用表达式:hasRole('ROLE_USER')
-->
<security:http auto-config="true" use-expressions="false">
<!-- 配置拦截的请求地址,任何请求地址都必须有ROLE_USER的权限 -->
<security:intercept-url pattern="/**" access="ROLE_USER"/>
</security:http>
<!-- 配置认证(登录)信息:认证管理器 -->
<security:authentication-manager>
<!--认证信息的提供者-->
<security:authentication-provider>
<!--用户服务对象-->
<security:user-service>
<!--用户信息:临时的账号和密码
{noop}:不使用加密
authorities:指定用户的认证角色
-->
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
三、web.xml配置
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--通过全局参数引入配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</context-param>
<!--委派代理过滤器链-->
<!--配置委派代理过滤器: filter-name必须是:springSecurityFilterChain -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--创建spring容器对象-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
当访问index.jsp时,就会进入认证页面(默认)
使用自定义页面
添加自定义页面
配置spring-security.xml
- 在原先的基础上,指定安全框架使用的页面,注意login页面请求的路径,只能为login
- 对登录、失败和favicon.ico进行放行
- 关闭跨站请求伪造
- 退出登录的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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
">
<!--对登录和失败页面放行-->
<security:http pattern="/login.jsp" security="none"></security:http>
<security:http pattern="/error.jsp" security="none"></security:http>
<security:http pattern="/favicon.ico" security="none"></security:http>
<!--
配置拦截的规则
auto-config="使用自带的页面"
use-expressions="是否使用spel表达式",如果使用表达式:hasRole('ROLE_USER')
-->
<security:http auto-config="true" use-expressions="false">
<!-- 配置拦截的请求地址,任何请求地址都必须有ROLE_USER的权限 -->
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<!--指定安全框架使用的页面-->
<!--
login-page:指定登录页面
login-processing-url:登录的请求路径,登录时必须使用该路径
default-target-url:登录成功后进入的页面
authentication-failure-url:认证失败要进入的页面
-->
<security:form-login login-page="/login.jsp"
login-processing-url="/login"
default-target-url="/success.jsp"
authentication-failure-url="/error.jsp"
></security:form-login>
<!--关闭跨站请求伪造-->
<security:csrf disabled="true"></security:csrf>
<!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp"/>
</security:http>
<!-- 配置认证(登录)信息:认证管理器 -->
<security:authentication-manager>
<!--认证信息的提供者-->
<security:authentication-provider>
<!--用户服务对象-->
<security:user-service>
<!--用户信息:临时的账号和密码
{noop}:不使用加密
authorities:指定用户的认证角色
-->
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
安全框架集成到项目
不指定用户
一、添加spring-security.xml
注意:需要对favicon.ico和静态资源放行
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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
">
<!--对登录和失败页面放行-->
<security:http pattern="/login.jsp" security="none"></security:http>
<security:http pattern="/error.jsp" security="none"></security:http>
<security:http pattern="/favicon.ico" security="none"></security:http>
<security:http pattern="/css/**" security="none"></security:http>
<security:http pattern="/img/**" security="none"></security:http>
<security:http pattern="/plugins/**" security="none"></security:http>
<!--
配置拦截的规则
auto-config="使用自带的页面"
use-expressions="是否使用spel表达式",如果使用表达式:hasRole('ROLE_USER')
-->
<security:http auto-config="true" use-expressions="false">
<!-- 配置拦截的请求地址,任何请求地址都必须有ROLE_USER的权限 -->
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<!--指定安全框架使用的页面-->
<!--
login-page:指定登录页面
login-processing-url:登录的请求路径,登录时必须使用该路径
default-target-url:登录成功后进入的页面
authentication-failure-url:认证失败要进入的页面
-->
<security:form-login login-page="/login.jsp"
login-processing-url="/login"
default-target-url="/index.jsp"
authentication-failure-url="/login.jsp"
></security:form-login>
<!--关闭跨站请求伪造-->
<security:csrf disabled="true"></security:csrf>
<!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp"/>
</security:http>
<!-- 配置认证(登录)信息:认证管理器 -->
<security:authentication-manager>
<!--认证信息的提供者-->
<security:authentication-provider>
<!--用户服务对象-->
<security:user-service>
<!--用户信息:临时的账号和密码
{noop}:不使用加密
authorities:指定用户的认证角色
-->
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
二、web.xml
配置委派代理过滤器链,并引入spring-security.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--全局参数,指定配置文件的路径-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml,classpath:spring-security.xml</param-value>
</context-param>
<!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<!--委派代理过滤器链-->
<!--配置委派代理过滤器: filter-name必须是:springSecurityFilterChain -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
当访问项目的任何一个路径时,就会跳转到login页面
指定用户
一、在数据库中,添加sys_user表,并添加数据(注意oracle数据库一定要提交!)
二、创建实体类SysUser,注意不能创建User,User为安全框架的内置对象
三、创建UserService接口,继承UserDetailsService
/**
* UserDetailsService:接口中提供了一个方法,loadUserByUsername
*/
public interface UserService extends UserDetailsService {
}
四、实现接口
- 重写
loadUserByUsername
方法,会将页面中输入的username
传递过来 - 创建UserDao接口,根据
username
查询用户对象 - 当用户不为空时,创建角色集合对象,并添加角色对象(此处为临时角色对象)
- 创建UserDetails对象,将
username
、password
、角色集合对象
三个参数作为构造方法传入(User为实现类) - 返回UserDetails对象
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserDao userDao;
/**
* 通过用户名得到用户对象
* 创建用户详情对象,返回
* @param username
* @return UserDetails:用户详情
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名获取用户(SysUser)对象
SysUser sysUser = userDao.findByUsername(username);
if(sysUser!=null){
//创建角色集合对象
Collection<GrantedAuthority> authorities = new ArrayList<>();
//创建临时角色对象
SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
//对象添加到集合中
authorities.add(grantedAuthority);
/**
* 参数1:username
* 参数2:password
* 参数3:角色列表对象
*/
UserDetails user = new User(sysUser.getUsername(),"{noop}"+sysUser.getPassword(),authorities);
return user;
}
return null;
}
}
五、在配置文件中关联用户服务对象
<!-- 配置认证(登录)信息:认证管理器 -->
<security:authentication-manager>
<!--认证信息的提供者:关联用户服务对象,提供账号和密码-->
<security:authentication-provider user-service-ref="userServiceImpl">
<!--<!–用户服务对象–>
<security:user-service>
<!–用户信息:临时的账号和密码
{noop}:不使用加密
authorities:指定用户的认证角色
–>
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
</security:user-service>-->
</security:authentication-provider>
</security:authentication-manager>
此时,配置完成,当在login界面中输入数据库中存在的用户时,即可登录成功