本教程介绍了如何保护视图层,基于已登录用户的角色,使用Spring Security标签来显示/隐藏 Spring MVC Web应用程序的JSP/视图。
完整的工程结构如下所示 -


首先,为了使用Spring Security标签,我们需要在pom.xml中包括 spring-security-taglibs 标记库的依赖库,如下图所示:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>4.0.1.RELEASE</version> </dependency>
然后在下一步在 视图/JSP 包括这些标签库。如下代码所示 -
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
最后,我们就可以使用Spring Security表达式类似 hasRole,hasAnyRole 等。在视图中,如下图所示:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Welcome page</title>
</head>
<body>
Dear <strong>${user}</strong>, Welcome to Home Page.
<a href="<c:url value="/logout" />">Logout</a>
<br/>
<br/>
<div>
<label>View all information| This part is visible to Everyone</label>
</div>
<br/>
<div>
<sec:authorize access="hasRole('ADMIN')">
<label><a href="#">Edit this page</a> | This part is visible only to ADMIN</label>
</sec:authorize>
</div>
<br/>
<div>
<sec:authorize access="hasRole('ADMIN') and hasRole('DBA')">
<label><a href="#">Start backup</a> | This part is visible only to one who is both ADMIN & DBA</label>
</sec:authorize>
</div>
</html>
这里就是需要基于角色这个有选择地显示/隐藏视图片段,使用Spring Security表达式在视图中。
以下是用于这个例子的 Security 配置:
package com.zaixian.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
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("zaixian").password("123456").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
auth.inMemoryAuthentication().withUser("dba").password("123456").roles("ADMIN","DBA");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/home").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
.and().formLogin().loginPage("/login")
.usernameParameter("ssoId").passwordParameter("password")
.and().exceptionHandling().accessDeniedPage("/Access_Denied");
}
}
上面的安全配置基于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-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<http auto-config="true" >
<intercept-url pattern="/" access="hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')" />
<intercept-url pattern="/home" access="hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')" />
<form-login login-page="/login"
username-parameter="ssoId"
password-parameter="password"
authentication-failure-url="/Access_Denied" />
</http>
<authentication-manager >
<authentication-provider>
<user-service>
<user name="zaixian" password="123456" authorities="ROLE_USER" />
<user name="admin" password="123456" authorities="ROLE_ADMIN" />
<user name="dba" password="123456" authorities="ROLE_ADMIN,ROLE_DBA" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
下面是控制器的完整代码,如下所示 -
package com.zaixian.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 = "/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;
}
}
应用程序的其余部分代码和这个系列的其他教程文章是相同的。
部署和运行
如需要自己动手实践,可在文章底部提供的下载链接并点击下载本示例代码,这个项目的完整代码。它是在Servlet 3.0的容器(Tomcat7/8,本文章使用 Tomcat7)上构建和部署运行的。
提供用户登录凭据(用户名及密码),首先我们使用 zaixian 这个用户名登录如下所示 -


登录成功后可以看到,有限的信息显示页面上,如下图中所示 -


现在点击注销,并使用管理员角色登录,所下图中所示 -


提交登录成功后,你会看到使用ADMIN角色的操作访问,如下图中所示 -


现在注销登录,然后使用 DBA 角色登录,如下图中所示 -


提交登录成功后,你会看到与DBA角色相关的操作访问。


全部就这样(包教不包会)。下一篇教程文章将我们学习如何使用基于角色登录。这意味着可根据自己分配的角色,在登录成功后用户将重定向到不同的URL。


下载代码
参考
上一篇:
Spring Security注销登录实例
下一篇:
Spring Security基于角色登录实例

