浪费了二天去解决生产问题,我滴妈啊.那生产问题代码真是又臭又长,看得人都崩溃了.
在本章完成了登出/记住我/从数据库查询用户权限/获取用户信息.
让我们看一下最新的
<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')" />
<!-- 管理员才能进入的界面. -->
<intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')"/>
<!-- 拦截所有的url access 调用一个函数, true为通过,false为拒绝. 这里是要求有ROLE_USER角色 -->
<intercept-url pattern="/**" access="hasRole('ROLE_MEMBER')" />
<!--
login-page 登陆界面
authentication-failure-url 登陆出错返回的地址
default-target-url 默认跳转的目标位置.
login-processing-url 默认处理的url,默认是/login
-->
<form-login login-processing-url="/login" login-page="/login" authentication-failure-url="/login?error=1" default-target-url="/index.jsp" />
<!--
开启记住我功能,存储在cookie中
使用cookie的name是securityKey
存活时间是四周.
-->
<remember-me key="securityKey" token-validity-seconds="2419200"/>
<!--
logout-success-url 登出成功返回到主界面.
不配置默认返回到login界面.
-->
<logout logout-url="/logout" logout-success-url="/" invalidate-session="true"/>
</http>
<!-- 相当于 protected void configure(AuthenticationManagerBuilder auth) 主要配置使用什么来进行连接. -->
<!--
authorities-by-username-query 查询权限的语句
group-authorities-by-username-query 查询组权限的语句
users-by-username-query 查询用户的语句
-->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
/>
</authentication-provider>
</authentication-manager>
</beans:beans>
这里有一个注意点,因为配置了csrf的配置,所以在logout的时候一定要包含一个隐藏域,具体代码如下
<c:url var="logout" value="/logout"></c:url>
<form action="${logout }" method="POST">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<input name="submit" type="submit" value="登出" />
</form>
login,jsp具体代码如下
<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 id="remember_me" name="remember-me" type="checkbox" />
<label for="remember-me" class="inline">记住我</label>
</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>
记住我功能默认使用的是cookie,你可以再登陆成功后,查看自己的cookie来查看.
使用数据库来进行登陆验证,可以看到我们在authentication-manager中使用了jdbc-user-service来进行用户的认证.
此外还可以使用ldap来进行,
我这里使用的是默认的数据库权限配置,
默认情况下的三条查询语句为:
<jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="
select username, authority
from authorities
where username = ?"
group-authorities-by-username-query="
select g.id, g.group_name, ga.authority
from groups g, group_members gm, group_authorities ga
where gm.username = ? and g.id = ga.group_id and g.id = gm.group_id"
users-by-username-query="
select username,password,enabled
from users
where username = ?"
/>
我们也可以自定,都很简单.只是需要注意 权限一定要以ROLE开头,数据库的列要和查询语句保持一致.即可.
在JSP中获取用户的属性
需要使用到security的tags标签具体如下
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>首页</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<c:url var="logout" value="/logout"></c:url>
<form action="${logout }" method="POST">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<input name="submit" type="submit" value="登出" />
</form>
<p>假设我是首页</p>
<div>
<security:authorize access="hasRole('ROLE_MEMBER')">
<security:authentication property="principal.username" var="username"/>
用户名: <span>${username }</span>
</security:authorize>
</div>
</body>
</html>
Java 获取用户和用户权限,
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails) principal).getUsername();
Iterator it = ((UserDetails) principal).getAuthorities().iterator();
String authority = "";
while (it.hasNext()) {
authority = ((GrantedAuthority) it.next()).getAuthority();
System.out.println("Authority:" + authority);
}
}
基础配置说完, 下一节讲如果保护方法.