版权声明:由于本人水平有限,如有错误,不吝赐教。转载请注明出处 https://blog.csdn.net/qq_41001945/article/details/86296560
一、新建SpringBoot项目
二、修改配置文件
数据库结构
pom
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 解除thymeleaf对HTML语法的严查,不引入的话会有很多语法错误 -->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
我这里的springboot版本为2.1.1.RELEASE
application.yml
spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123321
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
logging.level.com.springsecurity.dao=debug
spring.mvc.view.prefix=templates/
spring.mvc.view.suffix=.html
前端页面
(1)public文件夹下的login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<title>登录</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row" style="margin-top: 20px;">
<div class="col-md-3">
<h2>登陆</h2>
<form action="mylogin" method="post">
<div class="form-group">
<label for="userName">Username</label>
<input type="text" class="form-control" id="userName" name="username" placeholder="Enter username">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Enter password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
(2)模板引擎下的login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<title>登录</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row" style="margin-top: 20px;">
<div class="col-md-3">
<h2>登陆</h2>
<form th:action="@{/mylogin}" method="post">
<div class="form-group">
<label for="userName">Username</label>
<input type="text" class="form-control" id="userName" name="username" placeholder="Enter username">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Enter password">
</div>
<div class="form-group" th:if="${param.error}">
<p th:if="${session.SPRING_SECURITY_LAST_EXCEPTION}">
<p th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}"></p>
</p>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
SpringSecurityConfig
package com.springsecurity.config;
import com.springsecurity.service.MyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.Md4PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserService myUserService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/login.html","/testlogin","/mylogin") // 不需要登录就可以访问
.permitAll()
.antMatchers("/user/**").hasAnyRole("USER") // 需要具有ROLE_USER角色才能访问
.antMatchers("/admin/**").hasAnyRole("ADMIN") // 需要具有ROLE_ADMIN角色才能访问
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/testlogin") // 设置登录页面
.loginProcessingUrl("/mylogin")
.defaultSuccessUrl("/index") // 设置默认登录成功后跳转的页面
;
}
// 密码加密方式
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
// 重写方法,自定义用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserService);
}
}
必要说明:
loginPage("/testlogin") 相当于一个普通请求。这里则需要发送到登陆页面
loginProcessingUrl("/mylogin") 登陆页面表单提交的action.必须为post请求
defaultSuccessUrl("/index") 登陆成功后,发送这个请求
Controller接受处理请求
package com.springsecurity.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
@Controller
public class UserController {
@GetMapping("/testlogin")
public String authenticationLogin() throws IOException {
return "login";
}
@GetMapping("/")
public String welcome(){
return "redirect:/login.html";
}
@GetMapping("/index")
@ResponseBody
public String index() throws IOException {
return "index html";
}
}
UserDetailService
package com.springsecurity.service;
import com.springsecurity.bean.User;
import com.springsecurity.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service
public class MyUserService implements UserDetailsService {
@Autowired
private UserDao userDao;
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//从数据库根据用户名获取用户信息
System.out.println(s);
User userByName = userDao.getUserByName(s);
//创建一个新的UserDetails对象,最后验证登陆的需要
UserDetails userDetails=null;
if(userByName!=null){
System.out.println(userByName.getPassword());
//创建一个集合来存放权限
Collection<GrantedAuthority> authorities = getAuthorities(userByName);
//实例化UserDetails对象
userDetails=new org.springframework.security.core.userdetails.User(s,userByName.getPassword(),true,true,true,true, authorities);
}
return userDetails;
}
private Collection<GrantedAuthority> getAuthorities(User user){
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
//注意:这里每个权限前面都要加ROLE_。否在最后验证不会通过
authList.add(new SimpleGrantedAuthority("ROLE_"+user.getRole()));
return authList;
}
}
Dao层
扫描二维码关注公众号,回复:
4882450 查看本文章
package com.springsecurity.dao;
import com.springsecurity.bean.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserDao {
@Select("SELECT * FROM user where username=#{s}")
public User getUserByName(String s);
}
实体类JavaBean
package com.springsecurity.bean;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@ToString
public class User{
private Integer id;
private String username;
private String password;
private String role;
}
启动boot项目,验证登陆
在经过测试的时候,我发现直接访问模板引擎下面的页面会报404而在resources下创建public文件夹,里面放html文件就不会出404. 因为模板引擎相当于我们传统的ssm项目里面的WEB-INF文件夹。是受保护的。不能重定向以及直接访问。 转发没问题。所以,两个不同页面下的请求发送会有一点点差别。具体看上面代码。
form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性:
1. login-page 自定义登录页url,默认为/login
2. login-processing-url 登录请求拦截的url,也就是form表单提交时指定的action
3. default-target-url 默认登录成功后跳转的url
4. always-use-default-target 是否总是使用默认的登录成功后跳转url
5. authentication-failure-url 登录失败后跳转的url
6. username-parameter 用户名的请求字段 默认为userName
7. password-parameter 密码的请求字段 默认为password
8. authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
9. authentication-success-forward-url 用于authentication-failure-handler-ref
10. authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
11. authentication-failure-forward-url 用于authentication-failure-handler-ref
12. authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用