Spring Security进阶
一、配置可匿名访问的资源
在spring-security.xml文件中配置,指定哪些资源可以匿名访问。
<!-- 指定匿名即可访问的资源,也就是不需要认证授权,就可以访问 -->
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/js/**"/>
<security:http security="none" pattern="/login.html"/>
二、使用指定的登录页面
1. 提供login.html作为项目的登录页
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/login.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
2. 指定登录页面
指定login.html页面可以匿名访问,否则无法访问。
<security:http security="none" pattern="/login.html" />
3. 配置表单登录信息
<!--
security:form-login : 用于配置登录的表单页面信息
login-page : 登录页面是哪个
username-parameter :用户名的那个name属性的值是什么
password-parameter : 密码的那个name属性的值是什么
login-processing-url : 登录的表单提交的地址是哪个
default-target-url : 登录成功之后,去到哪里
authentication-failure-url : 登录失败之后,去到哪里
always-use-default-target : 表示登录之后之后是否打开index首页。 true :表示一定会打开首页,false:不一定打开index.html
-->
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
always-use-default-target="true"
default-target-url="/index.html"
authentication-failure-url="/login.html"
/>
4. 关闭CsrfFilter过滤器
Spring-security采用盗链机制,其中_csrf使用token标识和随机字符,每次访问页面都会随机生成,然后和服务器进行比较,成功可以访问,不成功不能访问(403:权限不足)。
<!--加入csrf的忽略-->
<security:csrf disabled="true"/>
三、从数据库查询用户信息
如果我们要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个实现UserDetailsService接口的实现类,并按照框架的要求进行配置即可。框架会自动调用实现类中的方法并自动进行密码校验。
1. 定义UserService类,实现UserDetailsService接口
public class UserService implements UserDetailsService {}
2. 在spring-security.xml中配置认证管理
<!--
2. 认证管理:使用我们写好的认证的服务 :UserService
authentication-manager : 认证管理员
authentication-provider : 由它提供认证的规则
user-service-ref :表示使用的认证规则是我们写好的UserService这个类,当然,我们需要把这个类先交给spring管理。
user-service-ref="userService" ,里面的userService是托管类的id名字
-->
<bean id="us" class="com.itheima.security.UserService"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="us">
</security:authentication-provider>
</security:authentication-manager>**
四、对密码进行加密
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
spring security中的BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥 对密码进行加密。SHA系列是Hash算法,不是加密算法,使用加密算法意味着可以解密(这个与编码/解码一样),但是采用Hash处理,其过程是不可逆的。
(1)加密(encode):注册用户时,使用SHA-256+随机盐+密钥把用户输入的密码进行hash处理,得到密码的hash值,然后将其存入数据库中。
(2)密码匹配(matches):用户登录时,密码匹配阶段并没有进行密码解密(因为密码经过Hash处理,是不可逆的),而是使用相同的算法把用户输入的密码进行hash处理,得到密码的hash值,然后将其与从数据库中查询到的密码hash值进行比较。如果两者相同,说明用户输入的密码正确。
这正是为什么处理密码时要用hash算法,而不用加密算法。因为这样处理即使数据库泄漏,黑客也很难破解密码。
<!--
security:password-encoder : 使用什么密码加密技术
passwordEncoder : 表示使用BCryptPasswordEncoder
-->
<bean id="us" class="com.itheima.security.UserService"/>
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="us">
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
五、配置多种校验规则(对访问的页面做权限控制)
<security:intercept-url pattern="/index.html" access="isAuthenticated()"></security:intercept-url>
<security:intercept-url pattern="/a.html" access="isAuthenticated()"></security:intercept-url>
<security:intercept-url pattern="/b.html" access="hasAuthority('add')"></security:intercept-url>
<security:intercept-url pattern="/c.html" access="hasRole('ROLE_ADMIN')"></security:intercept-url>
<security:intercept-url pattern="/d.html" access="hasRole('ABC')"></security:intercept-url>
六、注解方式权限控制(对访问的Controller类做权限控制)
1:在spring-security.xml文件中配置组件扫描和mvc的注解驱动,用于扫描Controller
<context:component-scan base-package="com.primo"/>
<mvc:annotation-driven/>
2:在spring-security.xml文件中开启权限注解支持
<!--开启注解方式权限控制-->
<security:global-method-security pre-post-annotations="enabled" />
3:创建Controller类并在Controller的方法上加入注解(@PreAuthorize)进行权限控制。
七、退出登录
<!--
退出登录的配置
security:logout 用于设置退出登录
logout-success-url : 退出成功之后 ,要到什么页面去
logout-url : 退出登录提交的请求地址是什么
invalidate-session : 退出登录之后,是否要删除session,一般选择 true
-->
<security:logout logout-success-url="/login.html" logout-url="/logout.do" invalidate-session="true"/>