`

使用Spring Security进行Spring MVC的权限验证

 
阅读更多

https://www.tianmaying.com/tutorial/spring-security

 

Spring Security,这是一种基于Spring AOP和Servlet过滤器的安全框架。它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理身份确认和授权。在Spring Framework基础上,Spring Security充分利用了依赖注入(DI,Dependency Injection)和面向切面技术。今天我们就来学习一下如何利用Spring security方便的进行权限验证。

添加依赖

首先还是先定义我们所需要的依赖:

 

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
<dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

在本次学习中,我们仍然使用Spring Boot作为框架,同时引入我们的核心学习库:spring-boot-starter-security。模板引擎仍然选用我们熟悉的thymeleaf。最后使用了Spring Data Jpa+ hsqldb作为数据库。

系统设计

本次学习,我们将实现一个简单的有权限验证的系统,在权限验证上,我们还可以加上一个简单的用户角色判断的验证,这样,我们就有以下几个页面:

  • 首页 所有人可访问
  • 登录页 所有人可访问
  • 普通页 登录后的用户都可访问
  • 管理页 管理员可访问
  • 无权限提醒页 当一个用户访问了其没有权限的页面,需要有一个页面来对其进行提醒

页面确定后,我们来看看用户表需要哪些字段。为了简化处理,我们的用户表只需要用户名、密码以及一个角色字段来确定其身份即可。

这样,我们的简单系统设计就出来了,为了加深印象,我们先不管权限验证相关代码,我们先来实现整个简单的系统吧。

系统实现

数据访问层

首先我们需要一个数据层以及业务层为我们的业务逻辑提供支持,由于我们没有业务逻辑,业务逻辑层就省去了,只需要利用Spring Data JPA来实现一个简单数据访问层即可。

首先来定义一个User对象,设置用户名、密码、角色三个字段:

 

@Entity
public class User {

    @Enumerated(EnumType.STRING)
    private ROLE role;

    @Id
    private String username;

    private String password;

    ...

}

然后定义UserRepository:

 

public interface UserRepository extends JpaRepository<User, Integer> {

    User findByUsername(String username);

}

这样,数据访问层就实现好了。

展现层

在展现层,我们需要提供系统设计中的所有页面。基于Spring MVC的Controller代码如下:

 

@Controller
public class HomeController {

    @RequestMapping(value = {"", "/home"}, method=RequestMethod.GET)
    public String home(){
        return "home";
    }

    @RequestMapping(value = "/helloadmin", method=RequestMethod.GET)
    public String helloAdmin(){
        return "helloAdmin";
    }

    @RequestMapping(value = "/hellouser", method=RequestMethod.GET)
    public String helloUser(){
        return "helloUser";
    }

    @RequestMapping(value = "/login", method=RequestMethod.GET)
    public String login(){
        return "login";
    }

    @RequestMapping("/403")
    public String forbidden(){
        return "403";
    }

}

注:其中返回的页面在src/main/resources/templates下,都是最简单的HTML页面,这里不在赘述。

 

关于Spring MVC的介绍情参考:Spring MVC快速入门

 

大家可以看到,最后一个403页面实际上应该是当用户访问了没有权限的页面后显示的页面,因此在这里我们需要设置:当发现请求的返回码是403时,需要交给'/403'进行处理。

 

@Configuration
public class ErrorPageConfig {

    @Bean
    public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
        return new MyCustomizer();
    }

    private static class MyCustomizer implements EmbeddedServletContainerCustomizer {

        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
        }

    }

}

这里我们利用了Spring自带的EmbeddedServletContainerCustomizer进行设置。当Spring发现有类型为EmbeddedServletContainerCustomizer注册进来,便会调用EmbeddedServletContainerCustomizer的customize方法,此时,我们可以对整个Container进行设置,这里,我们添加了对于返回值为HttpStatus.FORBIDDEN的请求,将其交给/403进行处理。

启动程序

当然,我们还需要添加一个系统的启动函数,这个大家都应该很熟悉了,没有用过Spring Boot的同学可以参考教材Spring Boot应用开发

 

@SpringBootApplication
public class App {

    public static void main( String[] args ){
        SpringApplication.run(App.class, args);
    }
}

初始化数据

最后,让我们准备一些测试数据:

 

@Service
public class DataInit {

    @Autowired UserRepository userRepository;

    @PostConstruct
    public void dataInit(){
        User admin = new User();
        admin.setPassword("admin");
        admin.setUsername("admin");
        admin.setRole(User.ROLE.admin);
        userRepository.save(admin);

        User user = new User();
        user.setPassword("user");
        user.setUsername("user");
        user.setRole(User.ROLE.user);
        userRepository.save(user);
    }

}

现在,一切准备就绪,进入根目录,运行mvn spring-boot:run,访问以下网页即可:

添加权限验证

上节内容我们搭建了一个简单的网页应用,但是其中完全没有任何登录、登出、权限验证等等的处理,只能保证每个页面的简单访问。接下来我们就来用Spring Security添加这些功能。

添加Spring Security配置

我们首先使用Spring Security帮我们做登录、登出的处理,以及当用户未登录时只能访问http://localhost:8080/以及http://localhost:8080/login两个页面。

从数据库中获取用户信息的操作是必不可少的,我们首先来实现UserDetailsService,这个接口需要我们实现一个方法:loadUserByUsername。即通过用户名加载与该用户的用户名、密码以及权限相关的信息。

 

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if(user == null){
            throw new UsernameNotFoundException("not found");
        }
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(user.getRole().name()));
        System.err.println("username is " + username + ", " + user.getRole().name());
        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(), authorities);
    }

}

然后我们添加一个SecurityConfig类来对Security进行配置,使AuthenticationManager使用我们的CustomUserDetailsService来获取用户信息:

 

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }

    @Override  
    protected void configure(AuthenticationManagerBuilder auth)  
            throws Exception {  
        auth.userDetailsService(userDetailsService());  
    }  

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/helloadmin")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

}

我们可以看到,SecurityConfig上添加了@EnableWebMvcSecurity标注,使得Spring Security提供并且支持了Spring MVC的集成。

同时,SecurityConfig还继承了WebSecurityConfigurerAdapter类,并覆盖了其中的几个方法:

  • userDetailsService()将我们自定义的CustomUserDetailsService实例化并添加进security的上下文当中
  • configure(AuthenticationManagerBuilder auth) 在该方法中,我们使AuthenticationManager使用CustomUserDetailsService作为其UserDetailsService实例。
  • configure(HttpSecurity http) 对URL进行权限配置,使得"/", "/home"不需要登录就可以访问,其他需要登录。登录的地址是'/login',当登录成功后将跳转到/helloadmin页面,并且登录、登出页面都是不需要登录就可以访问的。

这时候重启我们的应用,再次访问http://localhost:8080/hellouser,你会发现网页会自动跳转到登录页面,同时,我们的登录、登出功能已经实现好了。

实现一个UserDetailsService,再对Spring Security进行配置,这样,登录、登出以及登录的验证功能就可以实现啦,怎么样,是不是特别的简单。

添加角色验证

之前系统设计时,我们将用户分成了管理员与普通用户,那么,如何将这两类用户访问的页面分开,使得普通用户看不见管理员相关的页面呢?很简单,我们可以通过两行标注来实现这个功能,修改HomeController

 

@RequestMapping(value = "/helloadmin", method=RequestMethod.GET)
@PreAuthorize("hasAnyRole('admin')")
public String helloAdmin(){
    return "helloAdmin";
}

@RequestMapping(value = "/hellouser", method=RequestMethod.GET)
@PreAuthorize("hasAnyRole('admin', 'user')")
public String helloUser(){
    return "helloUser";
}

修改helloAdminhelloUser方法,添加@PreAuthorize标注,当我们访问这两个URL的时候,Spring Security会帮我们验证当前用户是否有权限访问该地址。

现在重新启动服务,用user账号登陆,访问'http://localhost:8080/helloadmin',怎么样,是不是看见403页面啦。添加角色控制,就是这么简单。

分享到:
评论

相关推荐

    SpringSecurity+MVC入门Demo

    通过这个"SpringSecurity+MVC入门Demo",初学者可以了解如何在Spring MVC应用中集成Spring Security,实现用户认证和授权的基本流程,为后续深入学习和实践打下基础。这个Demo应该包含了配置文件、控制器、视图和...

    基本的spring mvc + spring security实现的登录(无数据库)

    在本项目中,我们主要探讨的是如何利用Spring MVC和Spring Security框架构建一个基本的无数据库登录系统。Spring MVC是Spring框架的一部分,用于处理Web应用程序的请求-响应模型,而Spring Security则是一个强大的...

    spring security、 mybatis、 spring mvc 整合权限管理系统

    在IT领域,构建一个权限管理系统是企业级应用的常见需求,Spring Security、MyBatis和Spring MVC的整合正是实现这一目标的有效方式。这三个组件分别在不同的层面上为系统提供了强大的支持。 Spring Security是一款...

    spring security,mybatis,spring mvc 整合权限管理系统

    通过以上步骤,我们可以构建出一个完整的基于Spring Security、MyBatis和Spring MVC的权限管理系统,该系统既具备强大的安全防护,又具有灵活的数据操作和高效的应用架构。这样的系统可以满足大部分企业对权限管理的...

    Spring Security 资料合集

    - Spring Security 无缝集成于Spring MVC框架,可以方便地与Spring MVC的其他特性配合使用,如异常处理和模型映射。 10. **Spring Boot集成**: - 在Spring Boot项目中,Spring Security 可以通过自动配置快速...

    spring security用户权限项目

    在这个项目中,这三者协同工作,Spring Security 负责后台的权限控制,Spring MVC 处理业务逻辑和数据交互,而 jQuery Easy-UI 则提供了用户友好的界面。理解这些知识点对于开发和维护这样一个用户权限管理项目至关...

    最详细Spring Security学习资料(源码)

    授权:Spring Security提供了细粒度的授权机制,可以根据角色、权限进行访问控制。开发者可以通过配置或编程的方式定义哪些用户可以访问哪些资源。 攻击防护:Spring Security内置了对常见攻击(如跨站点请求伪造、...

    spring security + spring oauth2 +spring mvc SSO单点登录需要的最小jar包集合

    1. **身份验证中心(Authentication Server)**:使用Spring Security和Spring OAuth2建立一个独立的授权服务器,处理用户的登录请求,验证用户凭证,并生成访问令牌(Access Token)。 2. **资源服务器(Resource ...

    spring mvc 和spring security自定义登录

    当用户提交登录表单时,Spring Security的过滤器会捕获这个请求,然后调用我们之前配置的AuthenticationProvider进行验证。如果验证成功,用户会被重定向到主页或其他受保护的页面;反之,用户会收到错误消息。 ...

    spring_security_3.1

    7. **集成Spring MVC**:Spring Security 3.1与Spring MVC无缝集成,可以方便地保护Web控制器和视图。通过注解,如`@Secured`和`@PreAuthorize`,可以在方法级别声明安全约束。 8. **自定义逻辑**:Spring Security...

    java学习之SpringSecurity配置了登录链接无权限

    我们在使用SpringSecurity作为后台权限框架的时候,框架给我们提供了配置登录请求的接口,供我们配置登录链接,当我们配置了登录链接地址后,前端访问登陆请求的时候显示无权限。 异常分析 由于SpringSecurity的...

    spring-security实现复杂的权限管理

    Spring Security 是一个强大的且高度可定制的身份验证和访问控制框架,用于保护基于Java的应用程序。在Spring Security 3.17版本中,它提供了一套完整的解决方案来处理复杂的权限管理系统,包括用户认证、授权以及...

    spring security 官方文档

    10. **与其他Spring框架的集成**:Spring Security与Spring Boot、Spring MVC、Spring Data等其他Spring组件无缝集成,使得构建安全应用变得更加简单。 在Spring Security的官方文档中,包含了详细的配置指南、API...

    maven+springMVC+spring security权限实例

    【标题】"maven+springMVC+spring security权限实例"是一个综合性的IT项目,它展示了如何使用Maven构建一个基于Spring MVC和Spring Security的权限管理应用。这个实例旨在帮助开发者快速理解并实践这三大技术在实际...

    Spring Security 权限控制中文API

    这个“Spring Security 权限控制中文API”很可能是对Spring Security框架的中文文档或指南,帮助开发者理解和使用权限控制功能。 Spring Security的核心在于保护资源、进行身份验证(Authentication)和授权...

    SpringMVC集成SpringSecurity

    1. **SpringSecurity架构**:SpringSecurity的核心架构由多个组件构成,包括过滤器链、认证管理、权限控制等。其中,过滤器链是SpringSecurity处理请求的第一道防线,它会拦截所有HTTP请求并进行安全检查。 2. **...

    Spring mvc spring security Thymeleaf and Bootstrap

    Spring MVC、Spring Security、Thymeleaf 和 Bootstrap 是构建现代Web应用程序的重要技术栈。下面将分别详细介绍这些技术及其在后台管理中的应用。 1. Spring MVC: Spring MVC是Spring框架的一个模块,专门用于...

    最新java技术栈RBAC基于spring security与sping mvc分布式权限管理系统

    RBAC是一种权限管理模型,它将用户、角色和权限进行关联,允许管理员为不同角色分配不同的操作权限,提高了系统的安全性。 3. **分布式**:分布式系统是指由多台计算机组成的系统,它们通过网络互相通信,共同完成...

    springMVC注解+ security + redis 实例

    通过这个实例,你可以了解到如何在Spring MVC应用中使用注解简化开发,如何配置和使用Spring Security进行权限控制,以及如何利用Redis优化数据访问和会话管理。这样的实践对于提升个人技能和理解现代企业级应用的...

    整合 freemarker +spring security + spring MVC + spring DATA jpa 前端jtable 简单的crud

    本项目结合了Freemarker、Spring Security、Spring MVC和Spring Data JPA,旨在实现前端JTable的简单CRUD(创建、读取、更新、删除)功能。以下是这些技术的详细介绍及其在项目中的应用。 **Freemarker** 是一个...

Global site tag (gtag.js) - Google Analytics