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">© 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
这样就完成了
在需要编写文章的时候会自动跳到登录界面
访问慢了好多,后面加需要加缓存
相关文章推荐
- Spring Boot博客开发日常记录-添加简单的评论功能
- SpringBoot博客开发日常记录-搜索功能以及搜索词汇云图显示
- Spring Boot博客开发日常记录-加入Redis缓存
- Spring Boot 整合 Shiro 进行登录认证
- spring boot 整合 spring security 登录认证
- (看了之后保证学会超仔细)Springboot整合Spring security实现用户登录验证入门项目
- 基于SpringBoot从零构建博客网站 - 整合ehcache和开发注册登录功能
- Spring Boot实战之Filter实现使用JWT进行接口认证 jwt(json web token) 用户发送按照约定,向服务端发送 Header、Payload 和 Signature,
- spring-security 个性化用户认证流程——自定义登录页面(可配置)
- springboot中通用mapper结合mybatis generator的使用 通用mapper是为了方便开发人员对单表进行crud操作而产生的一套通用方法。 通用mapper只支持单表操作,可以
- 一步步开发自己的博客 番外篇(8、第三方登录及问题记录)
- spring boot MVC 三 用户注册和登录的实现
- 微信开发之获取OAuth2.0网页授权认证和获取用户信息进行关联(转:http://playxinz.iteye.com/blog/2249634)
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- Spring Security笔记:使用数据库进行用户认证(form login using database)
- 干货来袭,java用户登录与注销(前台+后台 框架springboot)
- shiro,基于springboot,基于前后端分离,从登录认证到鉴权,从入门到放弃
- SpringBoot整合Shiro实现登录认证的方法
- 【项目搭建】使用spring-boot进行REST风格的微服务开发入门
- springboot(十四):springboot整合shiro-登录认证和权限管理