spring security4学习(一)

本文介绍如何使用 Spring Security 进行 URL 访问控制,通过 Java 配置方式和 XML 方式展示用户授权及角色信息配置过程,并提供了一个实战案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文将分别介绍注解和xml的方式来使用spring security ,通过一个简单的demo来演示对url访问进行验证。

因为我用的是gradle来构建项目,先看一下gradle依赖项。


第一步:创建Spring Security Java 配置类。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/admin/**").access("hasRole('ADMIN')")
                .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
                .and().formLogin()
                .and().exceptionHandling().accessDeniedPage("/Access_Denied");
    }
}

上面这个类的configureGlobalSecurity方法里的 AuthenticationManagerBuilder配置用户授权和角色信息 。

AuthenticationManagerBuilder (权限管理器创建器)创建负责所有权限请求的AuthenticationManager(权限管理器),使用的是基于内存的权限认证。

重写Configure方法,来配置HttpSecurity 来配置基于特定http请求的安全认证。

只有具有ADMIN权限的用户才可以访问符合‘/admin/**’的url。只能够同时具有ADMIN 和 DBA权限的人才可以访问符合‘/db/**’ 的Url 。

formLogin 方法提供了基于表单的权限验证,将会产生一个默认的对用户的表单请求。

使用exceptionHandling().accessDeniedPage() ,在本例中它将获取所有的403(http访问拒绝)异常然后显示我们的用户定义的HTTP403页面。

对应的xml配置:

<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 auto-config="true" >  
        <intercept-url pattern="/" access="permitAll" />  
        <intercept-url pattern="/home" access="permitAll" />  
        <intercept-url pattern="/admin**" access="hasRole('ADMIN')" />  
        <intercept-url pattern="/dba**" access="hasRole('ADMIN') and hasRole('DBA')" />  
        <form-login  authentication-failure-url="/Access_Denied" />  
    </http>  
    
    <authentication-manager >  
        <authentication-provider>  
            <user-service>  
                <user name="bill"  password="abc123"  authorities="ROLE_USER" />  
                <user name="admin" password="root123" authorities="ROLE_ADMIN" />  
                <user name="dba"   password="root123" authorities="ROLE_ADMIN,ROLE_DBA" />  
            </user-service>  
        </authentication-provider>  
    </authentication-manager>  
        
       
</beans:beans>  

第二步:创建springSecurityFilte安全过滤器。

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}

对应在web.xml的l配置:

<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>  

第三步:创建SpringMVC 配置类。

@Configuration //标识一个类代替xml来配置bean容器
@EnableWebMvc //把WebMvcConfigurationSupport当成
// 配置文件来用,将其中所有标识有@Bean注解的方法配置成bean,这就成了Spring mvc的默认配置
@ComponentScan(basePackages = "security.controller")
@Import({ SecurityConfig.class })
public class AppConfig extends WebMvcConfigurerAdapter {

    @Bean //注解的方法都会发布成一个bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    /*@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //addResourceLocations指的是文件放置的目录,addResoureHandler指的是对外暴露的访问路径
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }*/
}
第四步:创建springmvc 初始化类
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}
初始化器继承自AbstractAnnotationConfigDispatcherServletInitializer ,它是所有WebApplicationInitializer 实现的基类。

在Servlet 3.0 环境下,通过实现WebApplicationInitializer 来配置ServletContext 。这意味着我们将不使用web.xml下支持servlet3.0容器发布应用。

第五步:创建Controller控制器

@Controller
public class HelloWorldController {

    @RequestMapping(value = { "/", "/home" }, method = RequestMethod.GET)
    public String homePage(ModelMap model) {
        model.addAttribute("greeting", "Hi, Welcome to mysite. ");
        return "welcome";
        /*ModelAndView model = new ModelAndView();
        model.addObject("greeting", "Spring Security Hello World");
        model.setViewName("hello");
        return model;*/
    }

    @RequestMapping(value = "/admin", method = RequestMethod.GET)
    public String adminPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "admin";
    }

    @RequestMapping(value = "/db", method = RequestMethod.GET)
    public String dbaPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "dba";
    }

    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "welcome";
    }

    @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)
    public String accessDeniedPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "accessDenied";
    }

    private String getPrincipal(){
        String userName = null;
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {
            userName = ((UserDetails)principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }

}
没有出现 /login,因为Spring Security默认会产生和处理。

注意退出:

首先我们在使用SecurityContextHolder.getContext().getAuthentication() 之前校验该用户是否已经被验证过。

然后调用SecurityContextLogoutHandler().logout(request, response, auth)  来退出。

logout 调用流程:

 1 将 HTTP Session 作废,解绑其绑定的所有对象。

 2 从SecurityContext移除Authentication 防止并发请求的问题。

 3 显式地清楚当前线程的上下文里的值。

在应用的其他地方不再需要处理 退出。

第六步:创建视图。

welcome.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>HelloWorld page</title>
</head>
<body>
	Greeting : ${greeting}
	This is a welcome page.
</body>
</html>
admin.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>HelloWorld Admin page</title>
</head>
<body>
	Dear <strong>${user}</strong>, Welcome to Admin Page.
	<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>
dba.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>DBA page</title>
</head>
<body>
	Dear <strong>${user}</strong>, Welcome to DBA Page.
	<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>
accessDenied.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>AccessDenied page</title>
</head>
<body>
	Dear <strong>${user}</strong>, You are not authorized to access this page
	<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>
第七步:发布应用到tomcat容器

通过gradle clean,gradle build 构建war包,war文件放到 tomcat的webapps目录下,然后运行 tomcat的bin目录下的startup.sh文件即可。

第八步:验证

打开浏览器访问:http://localhost:8140/springSecurityDemo-1.0-SNAPSHOT/

访问http://localhost:8140/springSecurityDemo-1.0-SNAPSHOT/admin,会被引导到登录页面


输入USER角色账户


提交之后,看到访问拒绝页面,AccessDenied


退出再次访问admin页面


输入错误的密码


输入正确的admin密码,再次登录,显示登录成功


访问http://localhost:8140/springSecurityDemo-1.0-SNAPSHOT/db得到访问拒绝页面


退出回到首页



最后上一张我的项目目录结构图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值