Spring Security快速入门
一、Spring Security概述
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作
二、基于配置使用Spring Security
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
web.xml配置filter
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</context-param>
<!--Spring监听-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--Spring Security过滤器-->
<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>
添加spring-security的配置
1.使用spring-security.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
<!--页面拦截规则-->
<security:http auto-config="true" use-expressions="false">
<!-- intercept-url 表示拦截页面,定义一个过滤规则
pattern:对哪些url进行权限控制
/* 表示的是该目录下的资源,只包括本级目录不包括下级目录
/** 表示的是该目录以及该目录下所有级别子目录的资源
access:请求对应的URL时需要什么权限,是一个以逗号分隔的角色列表,请求的用户只需拥有其中的一个角色就能成功访问对应的URL -->
<security:intercept-url pattern="/**" access="ROLE_USER" />
<!-- auto-config配置后,不需要在配置下面信息
<security:form-login /> form-login开启表单登陆,定义登录表单信息
<security:http-basic/>
<security:logout /> -->
</security:http>
<!--认证管理器-->
<security:authentication-manager>
<security:authentication-provider>
<!--在内存中存入用户名和密码-->
<security:user-service>
<!--{noop}是制定密码加密策略为不加密 。noop的意思是明文保存的密码 (noop: No Operation)-->
<security:user name="user" password="{noop}user"
authorities="ROLE_USER" />
<security:user name="admin" password="{noop}admin"
authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
制定加密策略为bcrypt
<security:user-service>
<!--修改配置文件中的password为bcrypt加密后的密码,并制定加密策略为bcrypt-->
<security:user name="user" password="{bcrypt}$2a$10$5r/POyb7K2wtbljfaY48K.1ie0l0qbuXYAdfdBEhVy1HLC3oqkix6"
authorities="ROLE_USER" />
<security:user name="admin" password="{bcrypt}$2a$10$5r/POyb7K2wtbljfaY48K.1ie0l0qbuXYAdfdBEhVy1HLC3oqkix6"
authorities="ROLE_ADMIN" />
</security:user-service>
2.使用SpringSecurityConfig配置类
创建SpringSecurityConfig配置类,继承WebSecurityConfigurerAdapter,并且该类需要加上@EnableWebSecurity注解,该类里面通常要写3个方法:
忽略某些配置的方法
public void configure(WebSecurity web) throws Exception {}
配置对应地址拦截请求的方法,例如拦截地址、关闭csrf、
protected void configure(HttpSecurity http) throws Exception {}
授权用户,比如创建某些账号,某些账号就可以登录了
protected void configure(AuthenticationManagerBuilder auth) throws Exception {}
@Component
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* UserServiceImpl是UserDetailsService的实现类,也就是写的认证类。
*/
@Autowired
private IUserService userService;
/***
* 忽略安全过滤
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
//忽略相关地址
web.ignoring().antMatchers("/images/**");
web.ignoring().antMatchers("/js/**");
web.ignoring().antMatchers("/login.html");
web.ignoring().antMatchers("/error.html");
}
/***
* 请求拦截配置
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//拦截规则配置
http.authorizeRequests()
//ADMIN角色可以访问/pages/下的所有文件
.antMatchers("/pages/**").access("hasRole('ADMIN')")
//USER角色可以访问/jsp/下的所有文件
.antMatchers("/jsp/**").access("hasRole('USER')")
//指定登录页和处理登录的地址
//.and().formLogin().loginPage("/login.html").loginProcessingUrl("/login")
//指定登出页和登出后让session无效
//.and().logout().logoutUrl("/logout").invalidateHttpSession(true);
//登录相关配置
http.formLogin().loginPage("/login.html") //指定登录地址
.loginProcessingUrl("/login") //指定处理登录的请求地址
.defaultSuccessUrl("/success.html",true); //登录成功后总是跳转到/admin/index.html页面
//登出配置
http.logout().logoutUrl("/logout").invalidateHttpSession(true); //登出地址为/logout,并且登出后销毁session
//设置用户只允许在一处登录,在其他地方登录则挤掉已登录用户,被挤掉的已登录用户则需要返回/login.html重新登录
http.sessionManagement().maximumSessions(1).expiredUrl("/login.html");
//关闭CSRF安全策略
http.csrf().disable();
/允许跳转显示iframe
http.headers().frameOptions().disable();
//异常处理,例如403
http.exceptionHandling().accessDeniedPage("/error.html");
//只允许一个用户登录,如果同一个账户两次登录,那么第一个账户将被踢下线,跳转到登录页面
http.sessionManagement().maximumSessions(1).expiredUrl("/login.html");
}
/***
* 创建用户并授权
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//方式1:创建一个用户存在内存中,账号是admin,密码是123456,角色是ROLE_ADMIN
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
auth.inMemoryAuthentication().withUser("user").password("user").roles("USER");
//方式2:自定义认证类后注册自定义认证类
// auth.userDetailsService(userService);
}
}
执行测试
创建一个index.html页面,当访问index.html时会弹出登录窗口,这是由于设置http的auto-config=”true”时Spring Security自动生成的。
错误用户名与密码登陆
使用用户名:user与密码:user登陆
使用用户名:admin和密码:admin登陆,报错403,权限不足。
因为<security:intercept-url pattern="/**" access="ROLE_USER" />配置访问url需要ROLE_USER角色,admin具有ROLE_ADMIN。
三、自定义登陆页面
spring-security.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
<!-- 配置不过滤的资源(静态资源及登录相关) -->
<security:http security="none" pattern="/login.html" />
<security:http security="none" pattern="/failer.html" />
<security:http auto-config="true" use-expressions="false" >
<!-- 配置资源连接,表示任意路径都需要ROLE_USER权限 -->
<security:intercept-url pattern="/**" access="ROLE_USER" />
<!-- 自定义登陆页面,login-page:自定义登陆页面
authentication-failure-url:用户权限校验失败之后跳转页面,如果数据库中没有这个用户则不会跳转到这个页面。
default-target-url:登陆成功后跳转页面。
登陆页面固定属性:用户名:username,密码:password,action:login -->
<security:form-login login-page="/login.html"
login-processing-url="/login" username-parameter="username"
password-parameter="password" authentication-failure-url="/failer.html"
default-target-url="/success.html" authentication-success-forward-url="/success.html"
/>
<!-- 关闭CSRF,默认是开启的 -->
<security:csrf disabled="true" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="user" password="{noop}user"
authorities="ROLE_USER" />
<security:user name="admin" password="{noop}admin"
authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
<csrf disabled="true"/>
为关闭跨域请求伪造控制。自定义登录静态页无法动态生成token,需要将此功能关闭。而spring security提供的表单默认有一个隐藏表单域,携带有token。一般静态页采用图形验证码的方式实现防止跨域请求伪造的功能。
创建页面
创建login.html,success.html,failer.html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="login" method="post">
<h1>自定义登陆表单</h1>
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录"/>
<input type="reset" value="重置"/></td>
</tr>
</table>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登陆成功!</h1>
</body>
</html>
执行测试
错误的用户名与密码登陆
正确的账户名与密码登陆
四、基于数据库认证使用Spring Security
Spring Security使用数据库认证登陆涉及常用类:UserDetails、UserDetailsService
UserDetails是一个接口,用于封装当前进行认证的用户信息,可以对其进行实现,也可以使用Spring Security提供的一个UserDetails的实现类User来完成相应操作
public interface UserDetails extends Serializable {
//账户所属角色集合
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
//帐户是否过期
boolean isAccountNonExpired();
//帐户是否锁定
boolean isAccountNonLocked();
//认证是否过期
boolean isCredentialsNonExpired();
//帐户是否可用
boolean isEnabled();
}
UserDetailsService:让自己的userService实现UserDetailsService接口,重写loadUserByUsername方法,实现认证逻辑,返回UserDetails
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
配置spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
<!-- 配置不拦截的资源 -->
<security:http pattern="/login.html" security="none"/>
<security:http pattern="/failer.html" security="none"/>
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/img/**" security="none"/>
<security:http pattern="/js/**" security="none"/>
<!--auto-config="true":使用框架提供的默认登录页面
use-expressions="false":是否使用SPEL表达式
-->
<security:http auto-config="true" use-expressions="false">
<!-- 配置具体的拦截规则
pattern:请求路径的规则
access:访问系统必须拥有的角色 -->
<security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>
<!-- 自定义登陆页面,定义跳转的具体的页面 -->
<security:form-login
login-page="/login.html"
login-processing-url="/login"
default-target-url="/success.html"
authentication-failure-url="/failer.html"
authentication-success-forward-url="/success.html"
/>
<!-- 关闭跨域请求 -->
<security:csrf disabled="true"/>
<!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.html" />
</security:http>
<!-- 使用数据库中的用户名和密码进行认证登陆 -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
</security:authentication-provider>
</security:authentication-manager>
</beans>
认证实现
public interface IUserService extends UserDetailsService {
}
@Service("userService")
public class UserServiceImpl implements IUserService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//TODO 查询数据库进行认证逻辑
//模拟查询得到的用户信息
String userName="user";
String password="user";
//构建角色集合,用户所拥有的角色
List<SimpleGrantedAuthority> roleList = new ArrayList<>();
roleList.add(new SimpleGrantedAuthority("ROLE_USER"));
//处理用户对象封装成UserDetails
UserDetails user=new User(userName,"{noop}"+password,roleList);
/**
* username 用户名
* password 密码
* enabled 帐户是否可用
* accountNonExpired 帐户是否过期
* credentialsNonExpired 认证是否过期
* accountNonLocked 帐户是否锁定
* authorities 账户所属角色集合
*/
// User user = new User(userName, "{noop}"+password, true, true, true, true, roleList);
return user;
}
}
退出操作
<!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.html" />
五、密码加密
BCrypt加密算法
用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储。 BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
由于md5对密码进行编码,每次算出的md5值都一样,这样非常不安全,Spring Security推荐使用BCryptPasswordEncoder对密码加随机盐,每次的Hash值都不一样,安全性高。
BCrypt官网 http://www.mindrot.org/projects/jBCrypt/
spring security官方推荐使用更加安全的bcrypt加密方式。spring security 5支持的加密方式有bcrypt、ldap、MD4、MD5、noop、pbkdf2、scrypt、SHA-1、SHA-256、sha256。
从官网下载源码后,将类BCrypt拷贝到工程即可使用.
public static void main(String[] args) {
//随机生成盐,共29个字符
String gensalt = BCrypt.gensalt();
System.out.println(gensalt);
//根据盐对密码进行加密
String password = BCrypt.hashpw("12345", gensalt);
//加密后的字符串前29位就是盐
System.out.println(password);
//密码校验
boolean checkpw = BCrypt.checkpw("12345", "$2a$10$5r/POyb7K2wtbljfaY48K.1ie0l0qbuXYAdfdBEhVy1HLC3oqkix6");
System.out.println(checkpw);
}
$2a$10$5r/POyb7K2wtbljfaY48K.
$2a$10$5r/POyb7K2wtbljfaY48K.1ie0l0qbuXYAdfdBEhVy1HLC3oqkix6
true
-----------------------------------------------------------
$2a$10$tHA2ZoRl2zX33wFmovKnr.
$2a$10$tHA2ZoRl2zX33wFmovKnr.e8qbj8/WSCmqSGXCurC.RAZPDJh7DfS
false
使用BCryptPasswordEncoder
真实开发中使用BCryptPasswordEncoder进行加密与校验。
@Test
public void passwrodEncoderTest(){
//原始密码
String password = "123";
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
//使用BCrypt加密,每次加密使用一个随机盐
for(int i=0;i<5;i++){
String encode = bCryptPasswordEncoder.encode(password);
System.out.println(encode);
//校验
boolean matches = bCryptPasswordEncoder.matches(password, encode);
System.out.println(matches);
}
}
配置加密
1.使用spring-security.xml配置
<!--使用自定义的认证类来认证用户信息-->
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
<!-- 配置加密的方式-->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!-- 配置加密类 -->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
2.使用配置类SpringSecurityConfig
<!--加密对象-->
<beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
@Autowired
private IUserService userService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
/****
* 用户授权
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//使用自定义的认证类实现授权
auth.userDetailsService(userService)
.passwordEncoder(bCryptPasswordEncoder); //指定加密对象
}
执行测试,生成;明文密码的加密密码
public static void main(String[] args) {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("user");
System.out.println("encode = " + encode );
}
encode = $2a$10$MQbfiELMnj4qtHCPe80mz.ZOHxzh1pcfgblgI0BGpg73Xekp/YjSm
在userServiceImpl的登陆认证方法中,修改模拟用户的明文密码为加密密码,此时,就可以省略密码前的{noop}标识。
@Service("userService")
public class UserServiceImpl implements IUserService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//TODO 查询数据库进行认证逻辑
//模拟查询得到的用户信息
String userName="user";
String password="$2a$10$MQbfiELMnj4qtHCPe80mz.ZOHxzh1pcfgblgI0BGpg73Xekp/YjSm";
//用户所拥有的角色
List<SimpleGrantedAuthority> roleList = new ArrayList<>();
roleList.add(new SimpleGrantedAuthority("ROLE_USER"));
//处理用户对象封装成UserDetails
UserDetails user=new User(userName,password,roleList);
/**
* username 用户名
* password 密码
* enabled 帐户是否可用
* accountNonExpired 帐户是否过期
* credentialsNonExpired 认证是否过期
* accountNonLocked 帐户是否锁定
* authorities 账户所属角色集合
*/
// User user = new User(userName, "{noop}"+password, true, true, true, true, roleList);
return user;
}
}
浏览器访问登陆
六、基于方法的权限控制
通过Spring security提供的注解对方法来进行权限控制,Spring Security在方法的权限控制上支持三种类型的注解,JSR-250注解、@Secured注解和支持表达式的注解,这三种注解默认都是没有启用的,需要单独通过global-method-security元素的对应属性进行启用。
JSR-250注解
1.添加依赖
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
2.spring-security.xml添加配置
<security:global-method-security jsr250-annotations="enabled"></security:global-method-security>
3.注解说明
@RolesAllowed:表示访问对应方法时所应该具有的角色。例如:@RolesAllowed({“USER”, “ADMIN”}) :表示该方法只要具有”USER”, “ADMIN”任意一种权限就可以访问。可以省略前缀ROLE_,实际的权限可能是ROLE_ADMIN
@PermitAll表示允许所有的角色进行访问,也就是说不进行权限控制
@DenyAll是和PermitAll相反的,表示无论什么角色都不能访问
4.使用注解
@Controller
public class TestController {
@RequestMapping("/test1.do")
@RolesAllowed("ADMIN")
public String test1(){
return "test1";
}
}
5.若jsr250注解不生效,需要在springmvc.xml中开启对AOP的支持,以及相关依赖包
<aop:aspectj-autoproxy proxy-target-class="true"/>
6.浏览器访问登陆,使用userServiceImpl类中模拟用户(用户名:user 密码:user 角色:ROLE_USER)
7.spring-security.xml配置的资源拦截规则,ROLE_USER允许访问,所以user登陆成功
8.由于test1.do资源访问需要ADMIN角色,而user用户无此角色,访问将报错403,可在web.xml中指定403错误跳转页面。
<error-page>
<error-code>403</error-code>
<location>/403.jsp</location>
</error-page>
@Secured注解
被@Secured注解标注的方法会得到权限控制的支持,其值默认为disabled,需要开启注解支持。
@Secured(“ROLE_ADMIN”):不可以省略前缀ROLE_,否则即使拥有某个权限也会报错403权限不足。
1. spring-security.xml添加配置
<security:global-method-security secured-annotations="enabled"></security:global-method-security>
2.使用注解
@Controller
public class TestController {
@RequestMapping("/test1.do")
@Secured("ROLE_ADMIN")
public String test1(){
return "test1";
}
}
3.执行测试,效果同使用JSR-250注解
支持表达式的注解
@PreAuthorize 在方法调用之前,基于表达式的计算结果判断是否拥有对应权限
@PostAuthorize 在方法调用之后,如果表达式计算结果为false,将抛出一个安全性异常
@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果
@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值
表达式 | 描述 |
---|---|
hasRole([role]) | 当前用户是否拥有指定角色。 |
hasAnyRole([role1,role2]) | 多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。 |
hasAuthority([auth]) | 等同于hasRole |
hasAnyAuthority([auth1,auth2]) | 等同于hasAnyRole |
Principle | 代表当前用户的principle对象 |
authentication | 直接从SecurityContext获取的当前Authentication对象 |
permitAll | 总是返回true,表示允许所有的 |
denyAll | 总是返回false,表示拒绝所有的 |
isAnonymous() | 当前用户是否是一个匿名用户 |
isRememberMe() | 表示当前用户是否是通过Remember-Me自动登录的 |
isAuthenticated() | 表示当前用户是否已经登录认证成功了。 |
isFullyAuthenticated() | 如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。 |
1.spring-security.xml添加配置
<security:global-method-security pre-post-annotations="enabled"></security:global-method-security>
2.使用注解
@Controller
public class TestController {
@RequestMapping("/test1.do")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String test1(){
return "test1";
}
@RequestMapping("/test2.do")
@PreAuthorize("authentication.principal.username=='user'")
public String test2(){
return "test1";
}
}
3.user用户只拥有USER角色,访问test1.do需要ADMIN角色,所以访问失败。
4.user用户用户名是“user”,满足访问test2.do的表达式条件,所以访问成功。
七、基于页面端标签控制权限
在jsp页面中可以使用spring security提供的权限标签来进行权限控制。
1.添加坐标依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
2.Jsp页面导入标签
<%@taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
3.标签说明
1.authentication
<security:authentication property="" htmlEscape="" scope="" var=""/>
authentication代表的是当前认证对象,可以获取当前认证对象信息,例如用户名。
property: 只允许指定Authentication所拥有的属性,可以进行属性的级联获取,如“principle.username”,不允许直接通过方法进行调用
htmlEscape:表示是否需要将html进行转义。默认为true。
scope:与var属性一起使用,用于指定存放获取的结果的属性名的作用范围,默认我pageContext。Jsp中拥有的作用范围都进行进行指定
var: 用于指定一个属性名,这样当获取到了authentication的相关信息后会将其以var指定的属性名进行存放,默认是存放在pageConext中
2.authorize
<security:authorize access="" method="" url="" var=""></security:authorize>
authorize是用来判断普通权限的,通过判断用户是否具有对应的权限而控制其所包含内容的显示
access: 需要使用表达式来判断权限,当表达式的返回结果为true时表示拥有对应的权限
method:method属性是配合url属性一起使用的,表示用户应当具有指定url指定method访问的权限,method的默认值为GET,可选值为http请求的7种方法
url:url表示如果用户拥有访问指定url的权限即表示可以显示authorize标签包含的内容
var:用于指定将权限鉴定的结果存放在pageContext的哪个属性中
3.accesscontrollist
<security:accesscontrollist hasPermission="" domainObject="" var=""></security:accesscontrollist>
accesscontrollist标签是用于鉴定ACL权限的。其一共定义了三个属性:hasPermission、domainObject和var,其中前两个必须指定
hasPermission:hasPermission属性用于指定以逗号分隔的权限列表
domainObject:domainObject用于指定对应的域对象
var:var则是用以将鉴定的结果以指定的属性名存入pageContext中,以供同一页面的其它地方使用
4.使用标签
<%@taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>我是Test1</h1>
<hr>
<p>
当前登陆人: <security:authentication property="principal.username"></security:authentication>
</p>
<hr>
<ul>
<li>
<security:authorize access="hasRole('ADMIN')">用户管理</security:authorize>
</li>
<li>
<security:authorize access="hasRole('USER')">角色管理</security:authorize>
</li>
</ul>
</body>
</html>
5.由于spring-security.xml中,配置use-expressions="false",表示不使用el表达式,在页面中使用标签是会报错,解决方法如下:
方法一:spring-security.xml中配置一个bean
<bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />
方法二:spring-security.xml启用el表达式
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
</security:http>
6.执行测试
八、AuthenticationSuccessHandler实现登录日志记录
spring security提供了一个叫“登录成功处理器”的组件,可以实现在登录后进行的后续处理逻辑。
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
/**
* 登录后执行该方法
*
* @param httpServletRequest
* @param httpServletResponse
* @param authentication 用户信息
* @throws IOException
* @throws ServletException
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
System.out.println("登录成功,记录日志");
String loginName = authentication.getName();
System.out.println(loginName);
String ip = httpServletRequest.getRemoteAddr();
System.out.println(ip);
httpServletRequest.getRequestDispatcher("/success.html").forward(httpServletRequest, httpServletResponse);
}
}
修改spring-security.xml
<beans:bean id="loginHandler" class="cn.ybzy.config.AuthenticationSuccessHandlerImpl"></beans:bean>
<!-- 设置登陆成功处理器 -->
<security:form-login
authentication‐success‐handler‐ref="loginHandler"/>
/>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137089.html