admin管理员组文章数量:1122920
进销存系统
代码地址:.git
一、引入SpringSecurity权限框架
为了快速方便实现进销存系统权限管理功能,系统引入SpringSecurity框架对应用权限进行统一控制。
1.1、使用SpringSecurity完成用户登录认证
1.1.1、jxc-admin pom.xml引入SpringSecurity坐标
<!--spring security 组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
1.1.2、JxcAuthenticationSuccessHandler.java
package com.xbmu.admin.config.security;import com.fasterxml.jackson.databind.ObjectMapper;
import com.xbmu.admin.model.RespBean;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 认证成功处理器** @author bitaotao* @since 2021-09-12*/
@Component
public class JxcAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {private static ObjectMapper objectMapper = new ObjectMapper();@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("application/json;charset=UTF-8");response.getWriter().write(objectMapper.writeValueAsString(RespBean.success("登录成功")));}
}
1.1.3、JxcAuthenticationFailedHandler.java
package com.xbmu.admin.config.security;import com.fasterxml.jackson.databind.ObjectMapper;
import com.xbmu.admin.model.RespBean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/**** 认证失败处理器* @author bitaotao* @since 2021-09-12*/
@Component
public class JxcAuthenticationFailedHandler extends SimpleUrlAuthenticationFailureHandler {private static ObjectMapper objectMapper = new ObjectMapper();@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {response.setContentType("application/json;charset=UTF-8");response.getWriter().write(objectMapper.writeValueAsString(RespBean.error("用户名或密码错误")));}
}
1.1.4、SpringSecurity配置类 SecurityConfig.java
package com.xbmu.admin.config.security;import com.xbmu.admin.pojo.User;
import com.xbmu.admin.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
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.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 javax.annotation.Resource;/*** SpringSecurity配置类* @author bitaotao* @since 2021-09-12*/
@SpringBootConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JxcAuthenticationSuccessHandler jxcAuthenticationSuccessHandler;@Autowiredprivate JxcAuthenticationFailedHandler jxcAuthenticationFailedHandler;@Resourceprivate IUserService userService;/*** 放行静态资源* @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/images/**","/css/**","/js/**","/lib/**","/error/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 禁用csrfhttp.csrf().disable()// 允许frame 页面嵌套.headers().frameOptions().disable().and().formLogin().usernameParameter("userName").passwordParameter("passWord").loginPage("/index").loginProcessingUrl("/login").successHandler(jxcAuthenticationSuccessHandler).failureHandler(jxcAuthenticationFailedHandler).and().authorizeRequests().antMatchers("/index","/login").permitAll().anyRequest().authenticated();}@Beanprotected UserDetailsService userDetailsService() {return new UserDetailsService() {@Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {// 根据用户名查询用户记录User userDetails = userService.findUserByUserName(userName);return userDetails;}};}/*** 配置 SpringSecurity 密码加密 Bean对象* @return*/@Beanpublic PasswordEncoder encoder(){return new BCryptPasswordEncoder();}/*** 配置认证Service接口与密码加密实现类* @param auth* @throws Exception*/protected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(encoder());}
}
1.1.5、User.java
package com.xbmu.admin.pojo;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.Collection;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;/*** <p>* 用户表* </p>** @author bitaotao* @since 2021-09-11*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable, UserDetails {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "主键id")@TableId(value = "id", type = IdType.AUTO)private Integer id;@ApiModelProperty(value = "备注名")private String bz;@ApiModelProperty(value = "密码")private String password;@ApiModelProperty(value = "真实姓名")private String trueName;@ApiModelProperty(value = "用户名")private String userName;@ApiModelProperty(value = "备注")private String remarks;@ApiModelProperty(value = "是否删除")private Integer isDel;@TableField(exist = false)Collection<? extends GrantedAuthority> authorities;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return this.authorities;}@Overridepublic String getUsername() {return userName;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}
1.1.6、UserController.java
删除UserController类中的login方法,引入了SpringSecurity框架,采用了SpringSecurity框架中的login方法。
1.1.7、UserServiceImpl.java
将该类中 user.getUserName()
代码 修改为 user.getUsername()
。因为user类实现了org.springframework.security.core.userdetails.UserDetails
接口,所有就采用UserDetails
接口中的方法。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.security.core.userdetails;import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();boolean isAccountNonExpired();boolean isAccountNonLocked();boolean isCredentialsNonExpired();boolean isEnabled();
}
1.1.8、测试
登录后,没有进入首页,而是又回到了登录页面。这是因为之前写的非法访问控制起了作用。
解决方法:删除非法访问控制代码(拦截器)。
<a href="javascript:;">${(Session.SPRING_SECURITY_CONTEXT.authentication.principal.username)!''}</a>
1.2、用户密码加密
1.2.1、密码修改对明文密码加密处理
使用SpringSecurity框架实现用户登录时,主要通过PasswordEncoder接口实现用户密码加密处理,核心实现类BCryptPasswordEncoder常用方法:
方法名 | 描述 |
---|---|
String encode(CharSequence rawPassword) | 字符串序列加密 |
boolean matches(CharSequence rawPassword, String encodedPassword) | 密码匹配,参数1为明文密码,参数2为加密密码,匹配成功返回true,反之false |
1.2.2、删除自定义的login方法
删除UserServiceImpl.java、IUserService.java类中的login方法
1.2.3、UserController.java
修改UserController类中updateUserPassword方法
/*** 用户密码更新* @param principal principal对象* @param oldPassword 旧密码* @param newPassword 新密码* @param confirmPassword 确认密码* @return*/@RequestMapping("updateUserPassword")@ResponseBodypublic RespBean updateUserPassword(Principal principal, String oldPassword, String newPassword, String confirmPassword){userService.updateUserPassword(principal.getName(),oldPassword,newPassword,confirmPassword);return RespBean.success("用户密码更新成功!");}
1.2.4、UserServiceImpl.java
package com.xbmu.admin.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xbmu.admin.pojo.User;
import com.xbmu.admin.mapper.UserMapper;
import com.xbmu.admin.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xbmu.admin.util.AssertUtil;
import com.xbmu.admin.util.StringUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** <p>* 用户表 服务实现类* </p>** @author bitaotao* @since 2021-09-11*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Resourceprivate PasswordEncoder passwordEncoder;@Overridepublic User findUserByUserName(String userName) {return this.baseMapper.selectOne(new QueryWrapper<User>().eq("is_del",0).eq("user_name",userName));}@Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)public void updateUserInfo(User user) {/*** 用户名:非空、唯一*/AssertUtil.isTrue(StringUtil.isEmpty(user.getUsername()),"用户名不能为空!");User tempUser = this.findUserByUserName(user.getUsername());AssertUtil.isTrue(null != tempUser && !(tempUser.getId().equals(user.getId())),"用户名已存在!");AssertUtil.isTrue(!(this.updateById(user)),"用户信息更新失败!");}@Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)public void updateUserPassword(String userName, String oldPassword, String newPassword, String confirmPassword) {/*** 用户名非空 必须存在* 原始密码 新密码 确认密码 均不能为空* 原始密码必须正确* 新密码 与 确认密码必须一致 并且不能与原始密码相同*/User user = this.findUserByUserName(userName);AssertUtil.isTrue(null==user,"用户不存在或未登录!");AssertUtil.isTrue(StringUtil.isEmpty(oldPassword),"请输入原始密码!");AssertUtil.isTrue(StringUtil.isEmpty(newPassword),"请输入新密码!");AssertUtil.isTrue(StringUtil.isEmpty(confirmPassword),"请输入确认密码!");AssertUtil.isTrue(!(passwordEncoder.matches(oldPassword,user.getPassword())),"原始密码输入错误!");AssertUtil.isTrue(!(newPassword.equals(confirmPassword)),"新密码输入不一致!");AssertUtil.isTrue(newPassword.equals(oldPassword),"新密码与原始密码不能一致!");user.setPassword(passwordEncoder.encode(newPassword));AssertUtil.isTrue(!this.updateById(user),"用户密码更新失败!");}
}
1.3、系统退出代码优化
1.3.1、JxcLogoutSuccessHandler.java
package com.xbmu.admin.config.security;import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 退出成功处理器** @author bitaotao* @since 2021-09-12*/
@Component
public class JxcLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.sendRedirect(request.getContextPath()+"/index");}
}
1.3.2、SecurityConfig.java
引入了SpringSecurity框架,采用了SpringSecurity框架中的signout方法。
package com.xbmu.admin.config.security;import com.xbmu.admin.pojo.User;
import com.xbmu.admin.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
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.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 javax.annotation.Resource;/*** SpringSecurity配置类* @author bitaotao* @since 2021-09-12*/
@SpringBootConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JxcAuthenticationSuccessHandler jxcAuthenticationSuccessHandler;@Autowiredprivate JxcAuthenticationFailedHandler jxcAuthenticationFailedHandler;@Resourceprivate IUserService userService;@Resourceprivate JxcLogoutSuccessHandler jxcLogoutSuccessHandler;/*** 放行静态资源* @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/images/**","/css/**","/js/**","/lib/**","/error/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 禁用csrfhttp.csrf().disable()// 允许frame 页面嵌套.headers().frameOptions().disable().and().formLogin().usernameParameter("userName").passwordParameter("passWord").loginPage("/index").loginProcessingUrl("/login").successHandler(jxcAuthenticationSuccessHandler).failureHandler(jxcAuthenticationFailedHandler).and().logout().logoutUrl("/signout").deleteCookies("JSESSIONID").logoutSuccessHandler(jxcLogoutSuccessHandler).and().authorizeRequests().antMatchers("/index","/login").permitAll().anyRequest().authenticated();}@Beanprotected UserDetailsService userDetailsService() {return new UserDetailsService() {@Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {// 根据用户名查询用户记录User userDetails = userService.findUserByUserName(userName);return userDetails;}};}/*** 配置 SpringSecurity 密码加密 Bean对象* @return*/@Beanpublic PasswordEncoder encoder(){return new BCryptPasswordEncoder();}/*** 配置认证Service接口与密码加密实现类* @param auth* @throws Exception*/protected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(encoder());}
}
1.3.3、测试
退出后,会删除cookies信息。
本文标签: 进销存系统
版权声明:本文标题:进销存系统 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1713136071a809266.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论