一、导入依赖
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
二、创建启动类:
/*
* Copyright (c) 2020, 2024, All rights reserved.
*
*/
package com.by;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
/**
* <p>Project: ican_parent - SpringSecurityApplication</p>
* <p>Powered by scl On 2024-01-29 10:44:12</p>
* <p>描述:<p>
*
* @author 孙臣龙 [1846080280@qq.com]
* @version 1.0
* @since 17
*/
@SpringBootApplication
//Map<"springSecurityFilterChain",FilterChainProxy> -----> FilterChainProxy ----->doFilterInternal()方法
@EnableWebSecurity //启动security
public class SpringSecurityApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringSecurityApplication.class, args);
Object bean = applicationContext.getBean("springSecurityFilterChain");
System.out.println("-----------------:"+bean.getClass());
}
}
三、编写配置类
/*
* Copyright (c) 2020, 2024, All rights reserved.
*
*/
package com.by.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
/**
* <p>Project: ican_parent - SecurityConfig</p>
* <p>Powered by scl On 2024-01-29 11:36:09</p>
* <p>描述:<p>
*
* @author 孙臣龙 [1846080280@qq.com]
* @version 1.0
* @since 17
*/
@Component
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限注解支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
/**
* 配置要放开的页面和配置静态资源
*
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
//web.ignoring().antMatchers("/pages/a.html");
//web.ignoring().antMatchers("/pages/**");
web.ignoring().antMatchers("/login.html");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
//关闭跨站请求
http.csrf().disable();
//认证
http.formLogin()
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/login") //表单的请求路径
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/pages/index.html", true);//登录成功后跳转的页面
//授权
http.authorizeRequests()
//.antMatchers("/pages/a.html").hasAuthority("aaa")
//.antMatchers("/pages/b.html").hasAuthority("bbb")
//.antMatchers("/pages/c.html").hasRole("CCC") //角色标识符不能用ROLE_开头
.anyRequest().authenticated();//登录成后,放开权限能够访问其它页面
//退出登录
http.logout().logoutUrl("/logout")
.logoutSuccessUrl("/login.html")
.invalidateHttpSession(true);
}
/**
* 加密方法,使用直接注入
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
四、UserServiceImpl
/*
* Copyright (c) 2020, 2024, All rights reserved.
*
*/
package com.by.service;
import com.by.pojo.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>Project: ican_parent - UserServiceImpl</p>
* <p>Powered by scl On 2024-01-29 16:37:34</p>
* <p>描述:<p>
*
* @author 孙臣龙 [1846080280@qq.com]
* @version 1.0
* @since 17
*/
@Component
public class UserServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
private Map<String, UserInfo> mysql = new HashMap<>();
public void initMysql() {
mysql.put("admin", new UserInfo("admin", passwordEncoder.encode("111")));
mysql.put("test", new UserInfo("test", passwordEncoder.encode("111")));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//初始化数据(类似与数据库)
initMysql();
//根据前端传过来的参数去数据库中查询
UserInfo userInfo = mysql.get(username);
if (userInfo == null) {
return null;
}
String password = userInfo.getPassword();//密码为明文
//模拟从数据库查询权限
List<GrantedAuthority> list = new ArrayList<>();
//通过用户名配置权限
if (username.equals("admin")) {
list.add(new SimpleGrantedAuthority("aaa"));
list.add(new SimpleGrantedAuthority("bbb"));
} else {
list.add(new SimpleGrantedAuthority("ROLE_CCC"));
}
//为什么不对比密码?程序员只需提供数据,对比密码归security管
return new User(username, password, list);
}
}
五、使用注解配置权限
/*
* Copyright (c) 2020, 2024, All rights reserved.
*
*/
package com.by.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
/**
* <p>Project: ican_parent - HelloController</p>
* <p>Powered by scl On 2024-01-29 19:50:41</p>
* <p>描述:<p>
*
* @author 孙臣龙 [1846080280@qq.com]
* @version 1.0
* @since 17
*/
@RestController
public class HelloController {
@RequestMapping("/aaa")
@PreAuthorize("hasAuthority('aaa')")
public String aaa() {
return "aaa";
}
@RequestMapping("/bbb")
@PreAuthorize("hasAuthority('bbb')")
public String bbb() {
return "bbb";
}
@RequestMapping("/ccc")
@PreAuthorize("hasRole('CCC')")
public String ccc() {
return "ccc";
}
@RequestMapping("/ddd")
@PreAuthorize("isAuthenticated()")
public String ddd() {
return "ddd";
}
/**
* 获取用户名
* @param authentication
* @return
*/
@GetMapping("/user")
public String getCurrentUser(Authentication authentication) {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String username = userDetails.getUsername();
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
// 这里可以根据需要获取更多的用户信息
return "用户名:" + username + ";角色:" + authorities;
}
}
六、实体类
package com.by.pojo;
public class UserInfo {
String username;
String password;
public UserInfo(String username,String password){
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "UserInfo{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
七、html页面
a.html、b.html、c.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>a 页面,你瞅啥!!!!</h1>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
就这就这就这!!!!<a href="/logout">退出登录</a><br>
<a href="/user">获取用户名</a>
</body>
</html>
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h3>自定义登录页面</h3>
<form action="/login" method="post">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>