前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 4 基于角色的登录例子(带源码)

Spring Security 4 基于角色的登录例子(带源码)

作者头像
明明如月学长
发布2021-08-27 15:19:25
1.2K0
发布2021-08-27 15:19:25
举报

原文网址: http://websystique.com/spring-security/spring-security-4-role-based-login-example/

【相关已翻译的本系列其他文章,点击分类里面的spring security 4】

【翻译by 明明如月 QQ 605283073】

上一篇:

Spring Security 4 安全视图片段 使用标签(Spring Security 标签)

下一篇:

Spring Security 4 Hibernate整合 注解和xml例子(带源码)

本教程将向你展示Spring Security 中基于 角色的登录。也就是说,根据其角色登录以后重定向到不同的url。

一般来说,我们需要自定义一个Success-Handler 来根据用户角色处理登录用户的重定向到对应的url。

这个功能在Spring Security 里面已经提供了。

SimpleUrlAuthenticationSuccessHandler 含有常用的success handler的常用逻辑。

我们仅需要拓展它,实现我们自己的逻辑即可。

一旦我们获得了successhandler(处理器),我们将通过formLogin()或loginPage()来注册它,

完整的例子如下:

--------------------------------------------------------

下面是用的技术

  • Spring 4.1.6.RELEASE
  • Spring Security 4.0.1.RELEASE
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

让我们开始吧

第1步: 项目文件目录结构

下面是最终的项目目录结构

现在让我为你展示上面目录结构里面的内容和每个的详细介绍。

第2步: 更新 pom.xml 包含所需的依赖
代码语言:javascript
复制
  4.0.0
 
  com.websystique.springsecurity
  SpringSecurityRoleBasedLoginExample
  1.0.0
  war
 
  SpringSecurityRoleBasedLoginExample
 
    
        4.1.6.RELEASE
        4.0.1.RELEASE
    
 
    
        
        
            org.springframework
            spring-core
            ${springframework.version}
        
        
            org.springframework
            spring-web
            ${springframework.version}
        
        
            org.springframework
            spring-webmvc
            ${springframework.version}
        
 
        
        
            org.springframework.security
            spring-security-web
            ${springsecurity.version}
        
        
            org.springframework.security
            spring-security-config
            ${springsecurity.version}
        
 
        
            javax.servlet
            javax.servlet-api
            3.1.0
        
        
            javax.servlet.jsp
            javax.servlet.jsp-api
            2.3.1
        
        
            javax.servlet
            jstl
            1.2
        
    
 
    
        
            
                
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    3.2
                    
                        1.7
                        1.7
                    
                
                
                    org.apache.maven.plugins
                    maven-war-plugin
                    2.4
                    
                        src/main/webapp
                        SpringSecurityRoleBasedLoginExample
                        false
                    
                
            
        
        SpringSecurityRoleBasedLoginExample
第3步: 添加 Spring Security 配置类

添加spring security到我们应用中第一步是要创建Spring Security Java 配置类。

这个配置创建一个叫springSecurityFilterChain的Servlet过滤器,来对我们应用中所有的安全相关的事项(保护应用的所有url,验证用户名密码,表单重定向等)负责。

代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
    @Autowired
    CustomSuccessHandler customSuccessHandler;
 
    @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").access("hasRole('USER')")
        .antMatchers("/admin/**").access("hasRole('ADMIN')")
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
        .and().formLogin().loginPage("/login").successHandler(customSuccessHandler)
        .usernameParameter("ssoId").passwordParameter("password")
        .and().csrf()
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");
    }
 
}

此类和前几篇文章类似,只是下面这点有区别: formLogin().loginPage("/login").successHandler(customSuccessHandler)

重点是successHandler,这个类定义了处理successHandler的逻辑。在本例中根据 角色USER/ADMIN/DBA重定向到home/admin/db 

以上配置 对应的xml配置文件:

代码语言:javascript
复制

下面是 上面的类里面涉及的 Success-Handler

代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
 
@Component
public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
 
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
 
    @Override
    protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {
        String targetUrl = determineTargetUrl(authentication);
 
        if (response.isCommitted()) {
            System.out.println("Can't redirect");
            return;
        }
 
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }
 
    /*
     * This method extracts the roles of currently logged-in user and returns
     * appropriate URL according to his/her role.
     */
    protected String determineTargetUrl(Authentication authentication) {
        String url = "";
 
        Collection authorities = authentication.getAuthorities();
 
        List roles = new ArrayList();
 
        for (GrantedAuthority a : authorities) {
            roles.add(a.getAuthority());
        }
 
        if (isDba(roles)) {
            url = "/db";
        } else if (isAdmin(roles)) {
            url = "/admin";
        } else if (isUser(roles)) {
            url = "/home";
        } else {
            url = "/accessDenied";
        }
 
        return url;
    }
 
    private boolean isUser(List roles) {
        if (roles.contains("ROLE_USER")) {
            return true;
        }
        return false;
    }
 
    private boolean isAdmin(List roles) {
        if (roles.contains("ROLE_ADMIN")) {
            return true;
        }
        return false;
    }
 
    private boolean isDba(List roles) {
        if (roles.contains("ROLE_DBA")) {
            return true;
        }
        return false;
    }
 
    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }
 
    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
 
}

注意:我们是怎样拓展 SimpleUrlAuthenticationSuccessHandler类的,重写了handle()方法,

简单的调用重定向使用配置的RedirectStrategy,其中通过determineTargetUrl方法返回对应的url 。

此方法从Authentication 对象中提取角色然后根据 角色构建 对应的url.最后在 Spring Security 负责所有重定向事务的RedirectStrategy (重定向策略)来重定向请求到指定的url

其余部分和以前的文章是一样的。

第4步: 注册springSecurityFilter

下面是定制初始化war包中的 springSecurityFilter(第三步中的) 注册类

代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
 
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
 
}

上面配置对应的xml配置如下:

代码语言:javascript
复制
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy

 

    springSecurityFilterChain
    /*
第5步: 添加 Controller(控制器)
代码语言:javascript
复制
package com.websystique.springsecurity.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HelloWorldController {
 
     
    @RequestMapping(value = { "/", "/home" }, method = RequestMethod.GET)
    public String homePage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "welcome";
    }
 
    @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 = "/Access_Denied", method = RequestMethod.GET)
    public String accessDeniedPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "accessDenied";
    }
 
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginPage() {
        return "login";
    }
 
    @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 "redirect:/login?logout";
    }
 
    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;
    }
 
}
第6步: 添加 SpringMVC 配置类
代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;
 
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springsecurity")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{
     
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
 
        return viewResolver;
    }
 
     /*
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
}

---------译者增加 start---明明如月-------- 以上配置对应的xml配置如下:

代码语言:javascript
复制
    /static/**" location="/static/" />

---------译者增加end---明明如月--------

第7: 添加Initializer(初始化器)类
代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { HelloWorldConfiguration.class };
    }
  
    @Override
    protected Class[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
 
}
第8步: 添加视图

login.jsp

此视图为登录面板增加了css

代码语言:javascript
复制
<%@ 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"%>

    
        
        Login page
        
        
        
    
 
    
        
            
                
                    
                        
                        
                            
                                
                                    Invalid username and password.
                                
                            
                            
                                
                                    You have been logged out successfully.

注意:和 CSRF 相关的是

代码语言:javascript
复制

这一行的目的是防止CSRF攻击。正如你所见jsp中CSRF参数使用EL表达式获取的。因此需要允许el表达式:

需要在jsp头添加如下一行:

代码语言:javascript
复制
<%@ page isELIgnored="false"%>

welcome.jsp

代码语言:javascript
复制
<%@ 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"%>


    
    Welcome page


    Dear ${user}, Welcome to Home Page.
    ">Logout

admin.jsp

代码语言:javascript
复制
<%@ 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"%>


    
    Admin page


    Dear ${user}, Welcome to Admin Page.
    ">Logout

dba.jsp

代码语言:javascript
复制
<%@ 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"%>


    
    DBA page


    Dear ${user}, Welcome to DBA Page.
    ">Logout

accessDenied.jsp

代码语言:javascript
复制
<%@ 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"%>


    
    AccessDenied page


    Dear ${user}, You are not authorized to access this page
    ">Logout

例子中所需的css文件

app.css

代码语言:javascript
复制
html{
    background-color:#2F2F2F;
}
 
body, #mainWrapper {
    height: 100%;
    background-image: -webkit-gradient(
    linear,
    right bottom,
    right top,
    color-stop(0, #EDEDED),
    color-stop(0.08, #EAEAEA),
    color-stop(1, #2F2F2F),
    color-stop(1, #AAAAAA)
);
background-image: -o-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -moz-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -webkit-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -ms-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: linear-gradient(to top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
}
 
body, #mainWrapper, .form-control{
    font-size:12px!important;
}
 
#mainWrapper {
    height: 100vh; 
    padding-left:10px;
    padding-right:10px;
    padding-bottom:10px;
}
 
#authHeaderWrapper{
    clear:both;
    width: 100%;
    height:3%;
    padding-top:5px;
    padding-bottom:5px;
}
 
.login-container {
    margin-top: 100px;
    background-color: floralwhite;
    width: 40%;
    left: 30%;
    position: absolute;
}
 
.login-card {
    width: 80%;
    margin: auto;
}
.login-form {
    padding: 10%;
}
第9步: 构建和部署应用

现在构建 war 包(通过eclipse或者myeclipse)或者通过maven 命令行(  mvn clean install). 在一个 Servlet 3.0 容器中发布本应用. 在这里我使用的是tomcat, 我将 war 文件放到  tomcat webapps 文件夹然后点击 tomcat安装目录的bin文件夹下的 start.bat .

启动应用

打开浏览器 在地址栏输入localhost:8080/SpringSecurityRoleBasedLoginExample/并回车

输入DBA角色的账户

提交表单,因为当前登录的用户时DBA角色,登录后将被重定向到/db 页面。

退出后登录 USER权限的用户

然后访问 admin 页面,将看到 权限拒绝页面

退出后登录 ADMIN 角色的账户

本文结束,下一篇文章我们精介绍基于Hibernate注解的数据库的Spring Security 权限验证。

项目下载地址: http://websystique.com/?smd_process_download=1&download_id=1495

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/05/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Security 4 安全视图片段 使用标签(Spring Security 标签)
  • Spring Security 4 Hibernate整合 注解和xml例子(带源码)
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档