-
Notifications
You must be signed in to change notification settings - Fork 2
spring security
程序安全性的两个主要方面是“认证”和”授权“,这两个概念都很好理解。
Spring Security 支持多种认证模式。这些验证绝大多数都是要么由第三方提供,或由相关的标准组织,如互联网工程任务组开发。另外Spring Security 提供自己的一组认证功能。
- BASIC
- OAnth2.0(微信QQ)
- LDAP
- CAS(政府企业)
授权方向主要有三种权限:
-
url权限:(authorizing web requests)授权web请求,允许url的跳转
-
方法权限:(authorizing whether methods can be invoked)授权方法是否可以被调用
-
数据权限:(authorizing access to individual domain object instances)授权可以访问数据域
可以在application.yml文件中配置信息。
使用Maven可能会用到以下依赖:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
使用spring security前的一些java配置
package com.example.conf;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
public SecurityWebApplicationInitializer() {
super(WebSecurityConfig.class);
}
}
SecurityWebApplicationInitializer作用:
-
自动为应用程序的每个URL注册 springSecurityFilterChain过滤器.
-
添加一个ContextLoadListener 用来载入 WebSecurityConfig(下面的).
package com.example.conf;
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("yiqun").password("123456")
.roles("USER");
}
}
WebSecurityConfig配置功能:
-
在你的应用程序中对每个URL进行验证
-
为你生成一个登陆表单(默认的,可以自己写新的)
-
允许使用用户名 ”yiqun“和密码 ”123456“使用验证表单进行验证。(并设置权限)
-
允许用户登出
-
CSRF attack CSPF攻击防范
-
Session Fixation Session保护
-
安全 Header 集成
-
和以下 Servlet API 方法集成
在WebSecurityConfig可以添加以下配置:
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/other/**");
//可以将CSS,JS等静态资源放在目录位置,将全部忽略跳过
}
WebSecurity和HttpSecurity 的区别是HttpSecurity 只能是url请求。
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/signup", "/about").permitAll() // #1
.antMatchers("/admin/**").hasRole("ADMIN") // #2
.anyRequest().authenticated() // #3
.and()
.formLogin()
.loginPage("/login") //#4
.permitAll() //#5
.and()
.logout() //#6
.logoutRequestMatcher(newAntPathRequestMatcher("/logout")) //#7
.logoutUrl("/logout") //#8
.logoutSuccessUrl("/login") //#9
.logoutSuccessHandler(logoutSuccessHandler) //#10
.invalidateHttpSession(true) //#11
.addLogoutHandler(logoutHandler) //#12
.deleteCookies(cookieNamesToClear) //#13
.and()
.httpBasic(); //#14
http.csrf()
.disable(); //#15
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); //#16
}
- 允许所有权限访问指定URL
- 设置只有指定 权限的人才能访问指定URL
- 除了以上指定URL , 其他访问都需要验证
- 自己指定登录URL,需要自己在controller写一个
- 允许所有用户访问所有基于表单登录的URL
- 提供注销支持 ,AntPathRequestMatcher会自动应用
- 提供注销支持并且指定跳转页面
- 设置触发注销操作的URL (默认是/logout,可以不写), 如果CSRF内启用(默认是启用的)的话这个请求的方式被限定为POST。
- 注销成功后跳转的URL(默认是/login?logout),指定url之后会跳到指定的注销页面,不会注销后二次登陆
- 自己设置logoutSuccessHandler,如果指定了这个选项那么logoutSuccessUrl()的设置会被忽略。
- 指定是否在注销时让HttpSession无效。 默认设置为 true 。
- 添加一个LogoutHandler.SecurityContextLogoutHandler默认添加最后一个LogoutHandler
- 允许指定在注销成功时将移除的cookie。
- 允许用户使用HTTP基于验证进行认证
- 禁用CSRF
- 开启CSRF,在页面有CSRF隐藏域的配置,必须使用#7
获取用户信息三种方式:SecurityContextHolder方法(后端),sec页面获取(添加依赖和页面开头),js方法从从session获取。
开发一般是自己重写从数据库获取的方式
方法权限service
package com.example.service;
@Service
public class MethodSecurityService {
@Secured("ROLE_ADMIN")
public String roleAdmin() {
String role = "我是一个admin";
return role;
}
@PreAuthorize("hasRole('ROLE_ADMIN' )and #num>5")
public void test1(int num) {
System.out.println("拥有权限并且数字大于5");
}
@PostAuthorize("returnObjict == 'abc'")
public String test2() {
System.out.println("执行方法并且返回一个字符对象");
return "abcd";
}
@PreAuthorize("hasAnyRole({'ROLE_ADMIN','ROLE_USER'})")
@PostFilter("hasRole('ROLE_ADMIN') || " + "filterObject.username == principal.username")
public List<User> test3() {
User u1 = new User("u1", "男", 19, "123");
User u2 = new User("u2", "女", 19, "123");
User u3 = new User("u3", "男", 19, "123");
List<User> list = new ArrayList<>();
list.add(u1);
list.add(u2);
list.add(u3);
return list;
}
@PreAuthorize("hasAnyRole({'ROLE_ADMIN','ROLE_USER'})")
@PostFilter("hasRole('ROLE_ADMIN') || " + "filterObject.username == principal.username")
public void test4(List<User> users) {
for (User user : users) {
System.out.println(user.getLoginName());
}
}
//以下内容为主要功能
public List<User> list = new ArrayList<>();
/**
* 显示所有用户信息
*/
public List<User> showList() {
return list;
}
/**
* 登陆后根据权限显示信息
*/
@PreAuthorize("hasAnyRole({'ROLE_ADMIN','ROLE_USER'})")
@PostFilter("hasRole('ROLE_ADMIN') || " + "filterObject.loginName == principal.username")
public List<User> userForm() {
User u1 = new User("admin", "123", 23, "男");
User u2 = new User("user", "123", 23, "男");
User u3 = new User("易群", "123", 23, "男");
list.add(u1);
list.add(u2);
list.add(u3);
for (int i = 0; i < list.size() - 1; i++) {
for (int j = list.size() - 1; j > i; j--) {
if (list.get(j).getLoginName().equals(list.get(i).getLoginName())) {
list.remove(j);
}
}
}
return list;
}
/**
* 根据用户名删除信息
*/
public List<User> delete(String del) {
for (User user : list) {
if (user.getLoginName().equals(del)) {
list.remove(user);
break;
}
}
return list;
}
}
登录页login:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<!-- Thymeleaf为我们提供的Spring Security的标签支持 -->
<head>
<meta charset="UTF-8" />
<title>登录页</title>
</head>
<body>
<form name='f' action='login' method='POST'>
<table>
<tr>
<td>用户名:</td>
<td><input type='text' name='username' value='admin'/></td>
</tr>
<tr>
<td>密码:</td><td><input type='password' name='password' value='123'/></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="Login"/></td>
</tr>
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}"
th:if="${_csrf}"/>
</table>
</form>
</body>
</html>
用户页hello:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<!-- Thymeleaf为我们提供的Spring Security的标签支持 -->
<head>
<meta content="text/html;charset=UTF-8" />
<title sec:authentication="name"></title>
<!-- 获得当前用户的用户名 -->
</head>
<body>
<fieldset >
<legend>登录用户:<span sec:authentication="name"></span>
登录角色:<span sec:authentication="principal.authorities"></span>
</legend>
<br></br>
<table border="1" align="center" id="tbl" >
<tr>
<th width="50px"><label th:text="用户名"></label></th>
<th width="50px"><label th:text="密码"></label></th>
<th width="50px"><label th:text="年龄"></label></th>
<th width="50px"><label th:text="性别"></label></th>
<th width="50px"><label th:text="删除"></label></th>
</tr>
<tr th:each="user: ${list}">
<td align="center" th:text="${user.loginName}"> </td>
<td align="center" th:text="${user.password}"> </td>
<td align="center" th:text="${user.age}"> </td>
<td align="center" th:text="${user.sex}"> </td>
<td align="center"><a th:href="@{'/delete?loginName='+${user.loginName}}">删除</a></td>
</tr>
</table>
<ul sec:authorize="isAnonymous()" >
<li><a th:href="@{/login}">Login </a></li>
<li><a th:href="@{/register}">Sign Up</a></li>
</ul>
<ul sec:authorize="isAuthenticated()">
<li><a th:href="@{logout}">Log out</a></li>
</ul>
<ul sec:authorize="isAuthenticated()">
<li><a th:href="@{'/add'}">添加</a></li>
</ul>
</fieldset>
</body>
<style type="text/css">
fieldset {
width: 500px;
height: 250px;
margin: 100px auto;
padding: 20px;
}
</style>
</html>
controller:
package com.example.controller;
@Controller
public class DemoController {
@Autowired
MethodSecurityService methodSecurityService;
/**
* 跳转到登录页面
*/
@GetMapping("/login")
public String login() {
return "login";
}
/**
* 登录成功跳转页面
*/
@GetMapping("/")
public String hello(Model model) {
@SuppressWarnings("unused")
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
model.addAttribute("list",methodSecurityService.userForm());
return "hello";
}
/**
* 显示所有信息
*/
@GetMapping("/show")
public String show(Model model) {
@SuppressWarnings("unused")
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
model.addAttribute("list",methodSecurityService.showList());
return "hello";
}
/**
* 根据用户名删除信息
*/
@GetMapping("/delete")
public String deletet(User user) {
methodSecurityService.delete(user.getLoginName());
return "redirect:show";
}
}