后端代码
spring-security.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:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--基于注解的权限控制-->
<!--开启注解方式权限控制-->
<!--
在Controller层方法上使用
@PreAuthorize("hasAuthority('add')")//表示用户必须拥有add权限才能调用当前方法
@PreAuthorize("hasRole('ROLE_ADMIN')")//表示用户必须拥有ROLE_ADMIN角色才能调用当前方法
-->
<security:global-method-security pre-post-annotations="enabled" />
<!--
【重要】【重要】【重要】
这里面的所有路径必须以/开头,否则启动报错
-->
<!--
http:用于定义相关权限控制
指定哪些资源不需要进行权限校验,可以使用通配符
静态资源过滤
-->
<security:http security="none" pattern="/js/**" />
<security:http security="none" pattern="/css/**" />
<!-- 静态资源过滤 匿名访问security="none" -->
<security:http pattern="/login.html" security="none"/>
<security:http pattern="/fail.html" security="none"/>
<!-- 拦截规则配置 -->
<!-- auto-config: 自动配置,自动生成login页面,login处理,退出处理
use-expressions: 是否使用spel表达式 true: access的值可以填表达式(hasRole, hasAuthority, hasAny....)
false: ROEL_角色名(必须是ROLE_打,否则启动报错), 或 security写死的几个常量
开启对表达式的支持
-->
<security:http auto-config="true" use-expressions="true">
<!-- pattern="/**" 拦截所有的路径 access="ROLE_ADMIN"
要访问符合pattern的url时,登陆用户必须有ROLE_ADMIN的角色,如果没有则不能访问
security:intercept-url: 拦截的url,pattern 拦截的url对应的格式,格式满足就拦截,可以配置多个
access:需要什么权限或角色才可以访问符合pattern的url
pattern="/**" access="ROLE_ADMIN": 只有ROLE_ADMIN角色的人才可以访问我的系统
-->
<!--只要认证通过就可以访问-->
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<!--
login-page:指定登陆页面login.html
login-processing-url: 告诉security哪个url请求才是做登陆认证,如果将来你的请求符合这个url,security就会帮我们去校验用户与密码,controller中的访问路径
username-parameter: 登陆时前端传过来的用户名的参数名, request.getParameter("参数名 abc"),前端的name属性值
password-parameter: 登陆时前端传过来的密码的参数名, request.getParameter("参数名 bbb"),前端的name属性值
authentication-failure-url: 登陆失败时跳转的路径
default-target-url: 默认登陆成功后跳转的路径
always-use-default-target: true:登陆成功后强制跳转到default-target-url里
false:登陆成功后跳转到未登录前访问的页面
-->
<security:form-login
login-page="/login.html"
login-processing-url="/login"
username-parameter="abc"
password-parameter="bbb"
authentication-failure-url="/fail.html"
default-target-url="/index.html"
always-use-default-target="true"
/>
<!--关闭跨域访问控制-->
<security:csrf disabled="true"/>
<!--
logout:退出登录
logout-url:退出登录操作对应的请求路径
logout-success-url:退出登录后的跳转页面
-->
<security:logout logout-url="/logout"
logout-success-url="/login.html" invalidate-session="true"/>
</security:http>
<!-- 认证管理器 -->
<security:authentication-manager>
<!--添加类实现UserDetailService接口,实现loadByUsername方法,且要返回UserDetails对象(用户名,数据库中的密码,用户所拥有的权限集合)-->
<!-- 认证信息提供者,认证信息的来源
提供登陆用户信息 用户名、密码、权限集合
users-service-ref 指向spring容器中一个bean对象, 实现这个UserDetailsService的对象, 提供用户的名称、密码、权限集合
一旦配置了user-service-ref,就不要配置security:users-service
-->
<security:authentication-provider user-service-ref="userService">
<security:password-encoder ref="encoder"/>
<!-- 登陆用户信息由我们自己来提供 -->
<!--<security:users-service>
<!– security:users 硬编码一个用户对象在内存中,就不需要去查询数据库了
将来应该使用从数据库查询
name: 登陆的用户名 password:登陆的密码
authorities: 指定的权限(既可以是角色名也可以权限名) authorities与上面access一致才能访问
{noop}使用的是明文,no operation 不要对密码做处理
–>
<security:users name="admin" password="{noop}admin" authorities="ROLE_ADMIN"/>
</security:users-service>-->
</security:authentication-provider>
</security:authentication-manager>
<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--登陆用户信息的提供者-->
<bean id="userService" class="com.heima.service.UserService"/>
</beans>
Controller层
@Controller
@RequestMapping
public class UserController {
@RequestMapping("/add")
@PreAuthorize("hasAuthority('add')")//表示用户必须拥有add权限才能调用当前方法
public String add(){
System.out.println("add...");
return "/success";
}
@RequestMapping("/update")
@PreAuthorize("hasRole('ROLE_ADMIN')")//表示用户必须拥有ROLE_ADMIN角色才能调用当前方法
public String update(){
System.out.println("update...");
return "/success";
}
@RequestMapping("/delete")
@PreAuthorize("hasRole('ABC')")//表示用户必须拥有ABC角色才能调用当前方法
public String delete(){
System.out.println("delete...");
return "/success";
}
}
前端页面
注意:以下操作的必须是在jsp文件中。
在前端页面顶部添加如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
获取当前用户
当前用户:<FONT color="red"> <security:authentication property="principal.username"/> </FONT>
设置访问权限
只有ROLE_ADMIN角色才能访问
<security:authorize access="hasRole('ROLE_ADMIN')">
<TD class=menuSmall>-用户管理</TD>
</security:authorize>
<security:authorize>标签的使用方法
<security:authorize>是一个流程控制标签,能够在满足特定安全需求的条件下显示它的内容体。它有三个互斥的参数:
ifAllGranted——是一个由逗号分隔的权限列表,用户必须拥有所有列出的权限时显示;
ifAnyGranted——是一个由逗号分隔的权限列表,用户必须至少拥有其中的一个权限时才能显示;
ifNotGranted——是一个由逗号分隔的权限列表,用户未拥有所有列出的权限时才能显示。
<security:authentication>获得属性的值
比如要获得用户名可以这么写:
<security:authentication property="principal.username"></security:authentication>
他有三个属性,property是必须的,另外scope和var,var定义一个变量,scope定义var存在的范围
例子:
有时需要在页面显示用户名,或者根据用户角色显示或者不显示一些内容。这需要使用到spring security提供的标签库。
在页面中引入标签库:
使用jstl表达式
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>