您的位置:首页 > 编程语言 > Java开发

Spring Boot博客开发日常记录-套用Spring Security进行用户登录认证

2019-04-28 22:30 369 查看

在之前的基础上,为了实现用户登录写文章的功能,加入了Spring Security进行用户认证登录,也就是SpringBoo 4000 t+ Spring Security

1. 创建用户表

第一步就是删除上次创建的用户表,然后新建用户表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_uuid` varchar(70) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`telephone` varchar(255) DEFAULT NULL,
`role` int(10) DEFAULT NULL,
`image` varchar(255) DEFAULT NULL,
`last_ip` varchar(255) DEFAULT NULL,
`last_time` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

2. 加入Spring Security依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

3. 重写User.java

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String user_uuid;   //用户UUID
private String username;    //用户名
private String password;    //用户密码
private String email;       //用户邮箱
private String telephone;   //电话号码
private String role;        //用户角色
private String image;       //用户头像
private String last_ip;     //上次登录IP
private String last_time;   //上次登录时间
public User(){}
public User(int id,String username){
this.id=id;
this.username=username;
}
public User(int id,String user_uuid,String username,String password,String role,String image){
this.id=id;
this.user_uuid=user_uuid;
this.username=username;
this.password=password;
this.role=role;
this.image=image;
}

public User(Integer id,String username,String password){
this.id=id;
this.username=username;
this.password=password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", user_uuid='" + user_uuid + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", telephone='" + telephone + '\'' +
", role='" + role + '\'' +
", image='" + image + '\'' +
", last_ip='" + last_ip + '\'' +
", last_time='" + last_time + '\'' +
'}';
}
}

4. 编写MyBatis相关函数

首先是在UserService.java中添加createUser()和findUserByUserName()函数

import com.nevergetme.nevergetmeweb.bean.User;

import java.util.List;

public interface UserService {
public List&
24000
lt;User> findAllUser();
public List<User> findUser(String username);
public User findUserByUserId(Integer id);
public User findUserByUserName(String username);
public User findUserByPhone(String phone);
public void createUser(User user);

//public List<User> findExistUser();
}

在UserServiceImpl.java中具体实现

import com.nevergetme.nevergetmeweb.bean.User;
import com.nevergetme.nevergetmeweb.mapper.UserMapper;
import com.nevergetme.nevergetmeweb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAllUser() {
List<User> list = userMapper.findAll();
return list;
}

@Override
public List<User> findUser(String username) {
List<User> list = userMapper.findUser(username);
return list;
}

@Override
public User findUserByUserId(Integer id) {
return userMapper.findUserByUserId(id);
}

@Override
public User findUserByUserName(String username) {
return userMapper.findUserByUserName(username);
}

@Override
public User findUserByPhone(String phone) {
return userMapper.findUserByPhone(phone);
}

@Override
public void createUser(User user) {
userMapper.createUser(user);
}
}

然后编写UserMapper.java中的这两个函数

import com.nevergetme.nevergetmeweb.bean.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface UserMapper {
public List<User> findAll();
public List<User> findUser(String username);
public User findUserByUserId(Integer id);
public User findUserByUserName(String username);
public User findUserByPhone(String phone);
public void createUser(User user);
}

最后是编写UserMapper.xml中的具体SQL

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.nevergetme.nevergetmeweb.mapper.UserMapper">
<resultMap id="userReusltMap" type="com.nevergetme.nevergetmeweb.bean.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="phone" property="phone"/>
</resultMap>
<select id="findAll" resultType="user">
select * from user
</select>
<select id="findUser" parameterType="java.lang.String" resultType="com.nevergetme.nevergetmeweb.bean.User">
select id,password from user where username=#{username}
</select>
<select id="findUserByUserName" parameterType="java.lang.String" resultType="com.nevergetme.nevergetmeweb.bean.User">
select * from user where username=#{username}
</select>
<select id="findUserByUserId" parameterType="java.lang.Integer" resultType="com.nevergetme.nevergetmeweb.bean.User">
select * from user where id=#{id}
</select>
<select id="findUserByPhone" parameterType="java.lang.String" resultType="com.nevergetme.nevergetmeweb.bean.User">
select * from user where phone=#{phone}
</select>
<insert id="createUser" parameterType="com.nevergetme.nevergetmeweb.bean.User">
insert into user(id,user_uuid,username,password,role,image)
values(#{id}, #{user_uuid}, #{username}, #{password}, #{role}, #{image})
</insert>
</mapper>

5. 构建用于登录的安全用户SecurityUser

import com.nevergetme.nevergetmeweb.bean.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class SecurityUser extends User implements UserDetails {
private static final long serialVersionUID = 1L;
public SecurityUser(User user) {
if (user != null) {
this.setId(user.getId());
this.setUser_uuid(user.getUser_uuid());
this.setUsername(user.getUsername());
this.setPassword(user.getPassword());
this.setEmail(user.getEmail());
this.setTelephone(user.getTelephone());
this.setRole(user.getRole());
this.setImage(user.getImage());
this.setLast_ip(user.getLast_ip());
this.setLast_time(user.getLast_time());
}
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities=new ArrayList<>();
String username = this.getUsername();
if(username!=null){
SimpleGrantedAuthority authority=new SimpleGrantedAuthority(username);
authorities.add(authority);
}
return authorities;
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
}

6. 设置访问策略类

import com.nevergetme.nevergetmeweb.bean.User;
import com.nevergetme.nevergetmeweb.security.SecurityUser;
import com.nevergetme.nevergetmeweb.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.core.Authentication;
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.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
@Override
protected void configure(HttpSecurity http) throws Exception { //配置策略
http.csrf().disable();
http.authorizeRequests().
antMatchers("/").permitAll().
antMatchers("/article/**").permitAll().
antMatchers("/article/showArticle/**").permitAll().
antMatchers("/icon/**").permitAll().
antMatchers("/js/**").permitAll().
antMatchers("/css/**").permitAll().
antMatchers("/plug/**").permitAll().
antMatchers("/source/**").permitAll().
antMatchers("/bootstrap/**").permitAll().
//                antMatchers("/createUser").permitAll().
antMatchers("/getCurrentUser").permitAll().
antMatchers("/editArticle").permitAll().anyRequest().authenticated().
and().formLogin().loginPage("/login").defaultSuccessUrl("/").permitAll().successHandler(loginSuccessHandler()).
and().rememberMe().tokenValiditySeconds(1209600).key("myKey").
and().logout().permitAll().invalidateHttpSession(true).
deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()).
and().sessionManagement().maximumSessions(10).expiredUrl("/login")

;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
auth.eraseCredentials(false);
}

@Bean
public BCryptPasswordEncoder passwordEncoder() { //密码加密
return new BCryptPasswordEncoder(4);
}

@Bean
public LogoutSuccessHandler logoutSuccessHandler() { //登出处理
return new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
try {
SecurityUser user = (SecurityUser) authentication.getPrincipal();
logger.info("USER : " + user.getUsername() + " LOGOUT SUCCESS !  ");
} catch (Exception e) {
logger.info("LOGOUT EXCEPTION , e : " + e.getMessage());
}
httpServletResponse.sendRedirect("/login");
}
};
}

@Bean
public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理
return new SavedRequestAwareAuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
User userDetails = (User) authentication.getPrincipal();
logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS !  ");
System.out.println("USER : " + userDetails.getUsername() + " LOGIN SUCCESS !  ");
super.onAuthenticationSuccess(request, response, authentication);
}
};
}
@Bean
public UserDetailsService userDetailsService() {    //用户登录实现
return new UserDetailsService() {
@Autowired
private UserService userRepository;

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepository.findUserByUserName(s);
if (user == null) throw new UsernameNotFoundException("Username " + s + " not found");
return new SecurityUser(user);
}
};
}
}

重要的是configure函数中的http

antMatchers("/").permitAll()//表示根目录不需要认证
antMatchers("/article/**").permitAll()//表示article目录下所有请求不需要认证即可访问
antMatchers("/editArticle").permitAll().anyRequest().authenticated()//表示/editArticle只允许认证的用户访问
formLogin().loginPage("/login").defaultSuccessUrl("/").permitAll().successHandler(loginSuccessHandler())//认证访问login页面,认证成功访问根目录
rememberMe().tokenValiditySeconds(1209600).key("myKey")//认证保存时长
logout().permitAll().invalidateHttpSession(true).
deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler())//访问logout时进行的操作

7. 编写controller类

@Controller
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(Model model){
return "login";
}

@RestController
@RequestMapping(value = "/getCurrentUser")
public @ResponseBody User getCurrentUser(){
return ContentUtility.getUser();
}
@RequestMapping(value = "/createUser", method = RequestMethod.POST)
public @ResponseBody
String createUser(
@RequestParam(value = "id", required = true) int id,
@RequestParam(value = "username", required = true) String username,
@RequestParam(value = "password", required = true) String password,
@RequestParam(value = "role", required = true) String role,
@RequestParam(value = "image", required = true) String image,
HttpServletRequest request,
HttpServletResponse response
) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(4);
User user = new User(id, ContentUtility.getRandomString(32), username, encoder.encode(password), role, image);
userService.createUser(user);
return "create user";
}

这里需要注意,我们首先要生成一个用户,需要调用/createUser接口,因此需要先将这个接口设置为antMatchers("/createUser").permitAll(),也就是将WebSecurityConfig.java中的那行注释去掉

8. 编写index.html和login.html

我写的login.html如下

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Signin Template · Bootstrap</title>

<link rel="canonical" href="https://getbootstrap.com/docs/4.3/examples/sign-in/">
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.css" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link th:href="@{/css/signin.css}" rel="stylesheet">
<script th:src="@{/js/jquery.min.js}"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script th:src="@{/js/bootstrap.min.js}"></script>
<script th:src="@{/js/popper.min.js}"></script>
</head>
<body class="text-center">
<form class="form-signin" action="/login" method="post">
<label for="username" class="sr-only">用户名</label><input id="username" type="text" name="username" class="form-control"/>
<label for="password" class="sr-only">密码</label><input id="password" type="password" name="password" class="form-control"/>
<input type="submit" value="登录">
<!--<img class="mb-4" src="/docs/4.3/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">-->
<!--    <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>-->
<!--    <label for="inputEmail" class="sr-only">Email address</label>-->
<!--    <input type="email"  class="form-control" required autofocus>-->
<!--    <label for="inputPassword" class="sr-only">Password</label>-->
<!--    <input type="password" id="inputPassword" class="form-control" placeholder="Password" required>-->
<!--    <div class="checkbox mb-3">-->
<!--        <label>-->
<!--            <input type="checkbox" value="remember-me"> Remember me-->
<!--        </label>-->
<!--    </div>-->
<!--    <button class="btn btn-lg btn-primary btn-block" type="button" id="SendInfo">Sign in</button>-->
<!--    <p class="mt-5 mb-3 text-muted">&copy; 2017-2019</p>-->
</form>
<script>
$(document).ready(function () {
$('#SendInfo').click(function () {
console.log("click here");
if($('#inputEmail').val()!=""&&$('#inputPassword').val()!=""){
$.post("/user/login",
{
userName:$("#inputEmail").val(),
password:$("#inputPassword").val()
},
function (data, status) {
console.log(data);
if(data.state=="1"){
history.back(-1);
}
//$('#receiverShow').text(data.output)
//$('#exampleModalCenter').modal(exampleModalCenter)
// alert("数据:" + data.output + "\n状态:" + status);
});
}
});
});

</script>
</body>
</html>

主要就是提交一个表单,注意表单的属性需要设置为username和password

这样就完成了
在需要编写文章的时候会自动跳到登录界面

访问慢了好多,后面加需要加缓存

项目地址
参考文献

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐