Spring Security权限控制

引言

Spring Security是一个能够为基于Spring的企业应用系统提供安全访问控制解决方案的安全框架,它利用Spring IOC、DI和AOP功能,为企业应用系统提供声明式的安全访问控制功能,简化企业系统为了安全控制而编写大量重复代码的工作,Spring Security支持Url级别的权限控制,同样也支持方法级别的权限控制,今天主要介绍Spring Security方法级别的权限控制。

Spring Security方法级别权限控制方式

Spring Security方法级别权限控制主要有以下几种方式:

• intercept-methods定义方法权限控制。

• 使用pointcut定义方法权限控制。

• 使用JSR-250注解定义方法权限控制。

• 使用@Secured注解定义方法权限控制。

• 注解使用表达式定义方法权限控制。

项目搭建

要想实现Spring Security方法级别的权限控制,必须先将项目搭建起来。

创建名称为Spring-Security的web项目

在pom.xml文件中引入相关的依赖包。

<dependencies>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>4.2.4.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>4.2.4.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-webmvc</artifactId>
 <version>4.2.4.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-support</artifactId>
 <version>4.2.4.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.security</groupId>
 <artifactId>spring-security-web</artifactId>
 <version>4.1.0.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.security</groupId>
 <artifactId>spring-security-config</artifactId>
 <version>4.1.0.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.8.7</version>
 </dependency>
 <dependency>
 <groupId>org.lucee</groupId>
 <artifactId>jsr250</artifactId>
 <version>1.0.0</version>
 </dependency>
</dependencies>

其中:

• spring-core、spring-web、spring-context-support是spring相关的依赖包。

• spring-webmvc是springmvc的依赖包。

• spring-security-web、spring-security-config是springsecurity相关的依赖包。

• aspectjweaver是aspectj的依赖包,用来实现pointcut方式的权限控制。

• jsr250是JSR-250标准的依赖包,用来实现jsr250注解方式的权限控制。

创建springmvc.xml和spring-security.xml配置文件。

创建springmvc.xml文件,用来扫描controller。

<?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: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/mvc
 http://www.springframework.org/schema/mvc/spring-mvc.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd">
 
 <context:component-scan base-package="com.itheima.demo" />
<mvc:annotation-driven />
</beans>

其中:

• context:component-scan是扫描controller注解配置。

• mvc:annotation-driven是开启springmvc注解。

创建spring-security.xml文件,用来进行springsecurity权限控制。

<?xml version="1.0" encoding="UTF-8"?>
<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">
<http pattern="/login.html" security="none"></http>
<http pattern="/login_error.html" security="none"></http>
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.html" default-target-url="/index.html" 
authentication-failure-url="/login_error.html"/>
<csrf disabled="true"/>
</http>
<authentication-manager id="authenticationManager">
<authentication-provider user-service-ref="userDetailService">
</authentication-provider>
</authentication-manager>
<beans:bean id="userDetailService" 
class="com.itheima.demo.user.UserDetailServiceImpl"></beans:bean>
</beans:beans>

其中:

• http:用来设置Url权限过滤规则,其中的security属性用来设置不受权限控制的行为,intercept-url用来设置访问资源所需的权限,form-login用来设置权限不足跳转的页面,这是设置的是我们自己创建的页面,csrf是关于csrf攻击的设置。

• authentication-manager:设置认证管理器,authentication-provider是配置认证提供者,这里我们通过创建的UserDetailServiceImpl来进行实现。

配置web.xml文件

在web.xml文件中加载springmvc.xml文件和spring-security.xml文件,处理springmvc乱码问题,设置springsecurity的拦截器。

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-security.xml</param-value>
 </context-param>
 <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <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>
 <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>
 <init-param>
 <param-name>forceEncoding</param-name>
 <param-value>true</param-value>
 </init-param>
 </filter>
 <filter-mapping>
 <filter-name>CharacterEncodingFilter</filter-name>
 <url-pattern>/ *</url-pattern>
 </filter-mapping>
 <servlet>
 <servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:spring/springmvc.xml</param-value>
 </init-param>
 </servlet>
 <servlet-mapping>
 <servlet-name>springmvc</servlet-name>
 <url-pattern>*.do</url-pattern>
 </servlet-mapping>

创建UserDetailServiceImpl

UserDetailServiceImpl用来进行权限认证,这里我们设置权限为ROLE_USER,会直接配置在spring-security.xml文件的authentication-provider中。

public class UserDetailServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("经过认证类:"+username);
List<GrantedAuthority> authorities=new ArrayList();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username,"123456",authorities);
}
}

创建UserController、UserService接口和UserServiceImpl接口实现类

创建UserController,调用Service中的操作

@RestController
public class UserController {
 @Autowired
 private UserService userService;
 @RequestMapping("/findAll")
 public void findAll(){
 userService.findAll();
 }
 @RequestMapping("/find")
 public void find(){
 userService.find();
 }
 @RequestMapping("/add")
 public void add(){
 userService.add();
 }
}

创建UserService接口

public interface UserService {
 public void findAll();
 public void find();
 public void add();
}

创建UserServiceImpl实现UserService接口,实现具体的操作

public class UserServiceImpl implements UserService {
 @Override
 public void findAll() {
 for (int i = 0; i < 5; i++) {
 System.out.println("商品"+i);
 }
 }
 @Override
 public void find() {
 System.out.println("商品");
 }
 @Override
 public void add() {
 System.out.println("添加商品");
 }
}

配置权限控制所需的index.html、login.html页面

index.html
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>登录成功</title>
</head>
<body>
登录成功
</body>
</html>
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登陆</title>
</head>
<body>
<form action="/login" method="post">
 用户名:<input name="username"/><br/>
 密码:<input type="password" name="password"/><br/>
 <button>登陆</button>
</form>
</body>
</html>

 

运行测试

启动项目,浏览器输入地址"http://localhost:8082/index.html"会出现如下效果:

 

「干货」SpringSecurity方法级别权限控制

 

 

说明权限控制已经开始起作用了,接下来就可以进行方法级别的权限控制了。

SpringSecurity方法级别权限控制

intercept-methods方式权限控制

在spring-security.xml文件中配置:

<beans:bean id="userServiceImpl" class="com.itheima.demo.service.UserServiceImpl">
 <intercept-methods>
 <protect method="add" access="ROLE_ADMIN"/>
 <protect method="find*" access="ROLE_USER"/>
 </intercept-methods>
</beans:bean>

其中:

• intercept-methods:需要定义在bean元素下,定义对当前的bean的某些方法进行权限控制。

• protect:配置访问方法所需的权限,需要指定两个属性,access和method,method表示需要拦截的方法名称,可以使用通配符,access表示执行对应的方法需要拥有的权限,多个权限之间可以使用逗号分隔。

运行测试

运行测试,当登录成功之后:

在浏览器输入"http://localhost:8082/find.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

在浏览器输入"http://localhost:8082/findAll.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/add.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

根据结果会发现当通过find.do或者是findAll.do进行请求时,因为在spring-security.xml文件配置了访问find*方法的访问权限是ROLEUSER,所以会直接通过controller调用service的方法来完成请求,但是当通过add.do进行请求时,因为在spring-security.xml文件配置了add方法的访问权限是ROLEADMIN,权限不对,所以会提示访问拒绝。

pointcut方式权限控制

使用pointcut方式进行权限控制,需要先引入aspectjweaver依赖包,同时需要在spring-security.xml文件中配置:

<beans:bean id="userServiceImpl"
class="com.itheima.demo.service.UserServiceImpl" />
<global-method-security>
<protect-pointcut
expression="execution(* com.itheima.demo.service.UserServiceImpl.find*())"
access="ROLE_USER"/>
<protect-pointcut
expression="execution(* com.itheima.demo.service.UserServiceImpl.add(..))"
access="ROLE_ADMIN"/>
</global-method-security>

其中:

• 基于pointcut的方法权限控制是通过global-method-security下的protect-pointcut来定义的。

• protect-pointcut:protect-pointcut中有两个属性,expression和access,可以通过expression设置切点表达式来进行设置拦截的方法,通过access设置访问权限。

运行测试

运行测试,当登录成功之后:

在浏览器输入"http://localhost:8082/find.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/findAll.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/add.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

根据结果会发现当通过find.do或者是findAll.do进行请求时,因为在spring-security.xml中的protect-pointcut中配置了访问find*方法的访问权限是ROLEUSER,所以会直接通过controller调用service的方法来完成请求,但是当通过add.do进行请求时,因为在spring-security.xml中的protect-pointcut配置了add方法的访问权限是ROLEADMIN,权限不对,所以会提示访问拒绝。

使用JSR-250注解方式权限控制

要使用JSR-250注解,首先需要引入jsr250依赖包,同时需要通过设置global-method-security元素的jsr250-annotation="enabled"来启用基于JSR-250注解的支持,默认为disabled,具体配置如下:

<beans:bean id="userServiceImpl" class="com.itheima.demo.service.UserServiceImpl" />
<global-method-security jsr250-annotations="enabled"/>
另外还需要在对应的java类中进行注解配置:

public class UserServiceImpl1 implements UserService {
 @RolesAllowed("ROLE_USER")
 @Override
 public void findAll() {
 for (int i = 0; i < 5; i++) {
 System.out.println("商品"+i);
 }
 }
 
 @DenyAll
 @Override
 public void find() {
 System.out.println("商品");
 }
 
 @RolesAllowed("ROLE_ADMIN")
 @Override
 public void add() {
 System.out.println("添加商品");
 }
}

其中:

• @RolesAllowed:设置访问对应方法时所应该具有的角色。

• @DenyAll: 表示无论什么角色都不能访问。

运行测试

运行测试,当登录成功之后:

在浏览器输入"http://localhost:8082/find.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/findAll.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/add.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

根据结果会发现当通过findAll.do进行请求时,因为配置了注解@RolesAllowed("ROLEUSER"),所以会直接通过controller调用service的方法来完成请求,但是通过find.do进行请求时,因为配置了@DenyAll不允许任何人访问,所以会提示访问拒绝,当通过add.do进行请求时,因为配置了@RolesAllowed("ROLEADMIN"),权限不对,所以会提示访问拒绝。

 

使用@Secured注解方式权限控制

@Secured是由Spring Security定义的用来支持方法权限控制的注解。它的使用也是需要启用对应的支持才会生效的。通过设置global-method-security元素的secured-annotations="enabled"可以启用,具体配置如下:

<beans:bean id="userServiceImpl" class="com.itheima.demo.service.UserServiceImpl" />
<global-method-security secured-annotations="enabled"/>
另外还需要在对应的java类中进行注解配置:

public class UserServiceImpl implements UserService {
 @Secured("ROLE_USER")
 @Override
 public void findAll() {
 for (int i = 0; i < 5; i++) {
 System.out.println("商品"+i);
 }
 }
 
 @Secured("ROLE_USER")
 @Override
 public void find() {
 System.out.println("商品");
 }
 
 @Secured("ROLE_ADMIN")
 @Override
 public void add() {
 System.out.println("添加商品");
 }
}

其中:

• @Secured:设置访问对应方法时所应该具有的角色。

运行测试

运行测试,当登录成功之后:

在浏览器输入"http://localhost:8082/find.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/findAll.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

在浏览器输入"http://localhost:8082/add.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

根据结果会发现当通过find.do或者是findAll.do进行请求时,因为配置了注解@Secured("ROLEUSER"),所以会直接通过controller调用service的方法来完成请求,但是当通过add.do进行请求时,因为配置的注解是@Secured("ROLEADMIN"),权限不对,所以会提示访问拒绝。

注解使用表达式方式权限控制

Spring Security中也可以使用表达式的注解来进行权限配置,它的使用也是需要在spring-security.xml中启用对应的支持才会生效的,具体配置如下:

<beans:bean id="userServiceImpl" class="com.itheima.demo.service.UserServiceImpl" />
<global-method-security pre-post-annotations="enabled"/>

另外还需要在对应的java类中进行注解配置:

public class UserServiceImpl implements UserService {
 @PreAuthorize("hasRole('ROLE_USER')")
 @Override
 public void findAll() {
 for (int i = 0; i < 5; i++) {
 System.out.println("商品"+i);
 }
 }
 
 @PreAuthorize("hasRole('ROLE_USER')")
 @Override
 public void find() {
 System.out.println("商品");
 }
 
 @PreAuthorize("hasRole('ROLE_ADMIN')")
 @Override
 public void add() {
 System.out.println("添加商品");
 }
}

其中:

• @PreAuthorize:使用表达式设置访问对应方法时所应该具有的角色。

运行测试

运行测试,当登录成功之后:

在浏览器输入"http://localhost:8082/find.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

 

在浏览器输入"http://localhost:8082/findAll.do",在开发工具的打印台会打印出如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

在浏览器输入"http://localhost:8082/add.do",会发现如下结果:

 

「干货」SpringSecurity方法级别权限控制

 

 

根据结果会发现当通过find.do或者是findAll.do进行请求时,因为配置了注解@PreAuthorize("hasRole('ROLEUSER')"),所以会直接通过controller调用service的方法来完成请求,但是当通过add.do进行请求时,因为配置的注解是@PreAuthorize("hasRole('ROLEADMIN')"),权限不对,所以会提示访问拒绝。

总结

方法级别的权限控制是Spring Security的权限控制方式之一,Spring Security可以通过intercept-methods对某个bean下面的方法进行权限控制,也可以通过pointcut对整个Service层的方法进行统一的权限控制,还可以通过注解定义对单独的某一个方法进行权限控制,使用方法级别的权限控制,可以实现细粒度的权限控制,使权限控制更具体细致。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值