权限管理02-springboot整合springsecurity

1 加入pom.xml

<!--Mysql数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!--mybatis-plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- jwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

2 配置application.properties

#serverPort
server.port=9001

#datasource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://xxx:3306/springboot-demo07-security?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.druid.initialSize=5
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=20
spring.datasource.druid.maxWait=60000
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.minEvictableIdleTimeMillis=300000
spring.datasource.druid.validationQuery=SELECT 1
spring.datasource.druid.testWhileIdle=true
spring.datasource.druid.testOnBorrow=true
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.poolPreparedStatements=true
spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.druid.filters=stat,wall
spring.datasource.druid.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1

#redis
spring.redis.host=xxx
spring.redis.port=6379
spring.redis.password=xxx
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=500
spring.redis.jedis.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=0

#thymeleaf
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

#mybatis-plus
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.configuration.auto-mapping-behavior=full
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.mapper-locations=classpath*:mapper/*Mapper.xml

#pageHelper
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.pageSizeZero=true
pagehelper.params=count=countSql

#jwt
jwt.header=Authorization
jwt.expire=604800
jwt.secret=ji8n3439n439n43ld9ne9343fdfer49h

3 security结构

 4 定义UserDetails(交给security管理的用户)

package com.grm.security.details;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

/**
 * 登录用户身份权限
 *
 * @author gaorimao
 * @date 2022/02/07
 */
public class LoginUser implements UserDetails {
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 已授予的权限
     */
    private Collection<? extends GrantedAuthority> authorities;

    public LoginUser(Long userId, String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

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

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

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

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

5 定义UserDetailsService实现

security自动进行数据库校验,只校验用户名,密码校验security自己封装实现了,如果要自定义密码校验,需要实现DaoAuthenticationProvider

package com.grm.security.details;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.grm.common.Result;
import com.grm.entity.SysUser;
import com.grm.service.SysUserService;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 用户验证处理
 *
 * @author gaorimao
 * @date 2022/02/07
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private HttpServletResponse response;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 根据用户名查用户
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        SysUser user = sysUserService.getOne(wrapper);
        if (ObjectUtils.isEmpty(user)) {
            Result.renderJsonStr(response,Result.failed(500,"登录用户:" + username + "不存在"));
        }
        return createLoginUser(user);
    }

    /**
     * 创建登录用户
     *
     * @param sysUser 系统用户
     * @return {@link UserDetails}
     */
    private UserDetails createLoginUser(SysUser sysUser) {
        List<GrantedAuthority> grantedAuthorities = getUserAuthority(sysUser.getId());
        return new LoginUser(sysUser.getId(), sysUser.getUsername(), sysUser.getPassword(), grantedAuthorities);
    }

    /**
     * 获取用户权限信息(角色、菜单权限)
     *
     * @param userId 用户id
     * @return {@link List}<{@link GrantedAuthority}>
     */
    private List<GrantedAuthority> getUserAuthority(Long userId) {
        // ROLE_admin,ROLE_normal,sys:user:list,....
        String authority = sysUserService.getUserAuthorityInfo(userId);
        //为用户分配权限,上面的配置类会根据权限来限制访问,产生不同结果。
        return AuthorityUtils.commaSeparatedStringToAuthorityList(authority);
    }
}

其中,查用户权限的代码 

package com.grm.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.grm.entity.SysMenu;
import com.grm.entity.SysRole;
import com.grm.entity.SysUser;
import com.grm.mapper.SysMenuMapper;
import com.grm.mapper.SysRoleMapper;
import com.grm.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统用户服务impl
 *
 * @author gaorimao
 * @date 2022/02/07
 */
@Slf4j
@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    /**
     * 获取用户权限信息(ROLE_admin,ROLE_normal,sys:user:list,sys:role:list)
     *
     * @param userId 用户id
     * @return {@link String}
     */
    public String getUserAuthorityInfo(Long userId) {
        String authority;
        // 1.获取角色代码
        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        String queryRoleIdsSql = "select role_id from sys_user_role where user_id = " + userId;
        sysRoleQueryWrapper.inSql("id", queryRoleIdsSql);
        List<SysRole> roles = sysRoleMapper.selectList(sysRoleQueryWrapper);
        String roleCodes = "";
        if (roles.size() > 0) {
            // 查询角色代码
            roleCodes = roles.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
        }
        authority = roleCodes.concat(",");
        // 2.获取权限代码
        // 2.1 如果角色有admin,默认所有菜单权限
        String menuPerms = "";
        if (roles.size() > 0) {
            List<SysRole> adminRoles = roles.stream().filter(role -> role.getCode().equals("admin")).collect(Collectors.toList());
            if (adminRoles.size() > 0) {
                List<SysMenu> menus = sysMenuMapper.selectList(null);
                // 查询菜单权限
                menuPerms = menus.stream().map(m -> m.getPerms()).collect(Collectors.joining(","));
            }else{
                menuPerms = getPermsAuthorityByUserId(userId);
            }
        }
        authority = authority.concat(menuPerms);
        return authority;
    }

    /**
     * 通过userId查询所有相关的menuIds
     *
     * @param userId 用户id
     * @return {@link String}
     */
    private String getPermsAuthorityByUserId(Long userId) {
        List<Long> menuIds = sysUserMapper.queryMenuIdsByUserId(userId);
        String menuPerms = "";
        if (menuIds.size() > 0) {
            List<SysMenu> menus = sysMenuMapper.selectBatchIds(menuIds);
            // 查询菜单权限
            menuPerms = menus.stream().map(m -> m.getPerms()).collect(Collectors.joining(","));
        }
        return menuPerms;
    }
}

如果要进行自定义密码验证,代码如下(一般如果有验证码功能的话需要加上这个步骤)

package com.grm.security.login;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * 自定义密码比对逻辑,需要自定义盐值时可使用此类
 *
 * @author gaorimao
 * @date 2022/02/08
 */
@Slf4j
public class PasswordCheckHandler extends DaoAuthenticationProvider {
    public PasswordCheckHandler(UserDetailsService userDetailsService) {
        super();
        // 这个地方一定要对userDetailsService赋值,不然userDetailsService是null
        setUserDetailsService(userDetailsService);
    }

    protected void additionalAuthenticationChecks(UserDetails userDetails,
                                                  UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        // authentication.getCredentials()得到的是密码
        if (authentication.getCredentials() != null) {
            String password = authentication.getCredentials().toString();
            String encodePassword = new BCryptPasswordEncoder().encode(password);

            String dbPassword = userDetails.getPassword();

            log.info("[PasswordCheckHandler] password = {},encodePassword = {} ,dbPassword = {}", password, encodePassword, dbPassword);

            if (!encodePassword.equals(dbPassword)) {
                throw new BadCredentialsException("密码错误!");
            }
        }
    }
}

6 实现UsernamePasswordAuthenticationFilter,获取json请求的登录参数

package com.grm.security.login;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * 登录参数为json格式时,security无法获取,需要重写下
 * <p>
 * 单体不分离项目不需要,直接form表单提交获取登录参数即可
 *
 * @author gaorimao
 * @date 2022/02/08
 */
@Slf4j
public class LoginParamFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (request.getMethod().equalsIgnoreCase("POST")) {
            ObjectMapper mapper = new ObjectMapper();
            InputStream inputStream;
            Map<String, String> authenticationBean;
            try {
                inputStream = request.getInputStream();
                authenticationBean = mapper.readValue(inputStream, Map.class);
                String username = authenticationBean.get("username");
                String password = authenticationBean.get("password");
                log.info("[LoginParam] username = {},password = {}", username, password);
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            } catch (IOException e) {
                throw new AuthenticationServiceException("Authentication method io exception: " + request.getMethod());
            }
        }
        // 只能是post请求
        throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
    }
}

7 登陆成功、登录失败、退出登录成功处理

登录成功(token返回给前端,token存储在redis中)

package com.grm.security.login;

import com.alibaba.fastjson.JSON;
import com.grm.common.Result;
import com.grm.security.details.LoginUser;
import com.grm.util.JwtUtil;
import com.grm.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

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

/**
 * 登录成功处理程序
 *
 * @author gaorimao
 * @date 2022-02-04
 */
@Slf4j
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        log.info("[Login] success,loginUser={}", JSON.toJSONString(loginUser));
        response.setContentType("application/json;charset=utf-8");
        String token = jwtUtil.createToken(loginUser.getUsername());
        // 把token存入redis缓存
        redisUtil.set(""+loginUser.getUsername(),token,60*60*24*7);
        Result result = Result.success("登录成功!",token);
        String jsonResult = JSON.toJSONString(result);
        PrintWriter out = response.getWriter();
        out.write(jsonResult);
        out.flush();
        out.close();
    }
}

登陆失败

package com.grm.security.login;

import com.alibaba.fastjson.JSON;
import com.grm.common.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

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

/**
 * 登录失败处理程序
 *
 * @author gaorimao
 * @date 2022-02-04
 */
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        Result result = Result.failed(500,"请检查用户名或密码是否正确!");
        String jsonResult = JSON.toJSONString(result);
        PrintWriter out = response.getWriter();
        out.write(jsonResult);
        out.flush();
        out.close();
    }
}

退出登录

package com.grm.security.logout;

import com.grm.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.io.PrintWriter;

/**
 * 退出登录成功
 *
 * @author gaorimao
 * @date 2022-02-08
 */
@Slf4j
@Component
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("{\"status\":\"ok\",\"msg\":\"登出成功\"}");
        out.flush();
        out.close();
    }
}

8 鉴权失败(匿名用户和已认证的用户)

匿名用户鉴权失败

package com.grm.security.perms;

import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

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

/**
 * AuthenticationEntryPoint用来解决匿名用户访问无权限资源时的异常
 *
 * @author gaorimao
 * @date 2022/02/08
 */
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.sendError(HttpStatus.UNAUTHORIZED.value(),exception.getMessage());
    }
}
认证过的用户鉴权失败
package com.grm.security.perms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

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

/**
 * AccessDeniedHandler用来解决认证过的用户访问无权限资源时的异常
 *
 * @author gaorimao
 * @date 2022/02/08
 */
@Slf4j
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception) throws IOException, ServletException {
        response.sendError(HttpStatus.UNAUTHORIZED.value(), exception.getMessage());
    }
}

9 security核心配置类(SecurityConfig)

package com.grm.security;

import com.grm.security.details.UserDetailsServiceImpl;
import com.grm.security.login.LoginFailureHandler;
import com.grm.security.login.LoginParamFilter;
import com.grm.security.login.LoginSuccessHandler;
import com.grm.security.logout.LogoutSuccessHandlerImpl;
import com.grm.security.perms.MyAccessDeniedHandler;
import com.grm.security.perms.MyAuthenticationEntryPoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * security配置认证和授权
 *
 * @author gaorimao
 * @since 2022-02-03
 */
@Slf4j
@Configuration
//开启Spring Security的功能
@EnableWebSecurity
//prePostEnabled属性决定Spring Security在接口前注解是否可用@PreAuthorize,@PostAuthorize等注解,设置为true,会拦截加了这些注解的接口
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 放行的资源列表
     */
    private static final String[] PASS_URL = {"/", "/login", "/index", "/logout", "/css/**", "/image/**", "/js/**", "/LightYear/**"};

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;
    @Autowired
    private LoginFailureHandler loginFailureHandler;
    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 定义异常返回信息
        http.exceptionHandling()
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDeniedHandler);
        // CSRF禁用,因为不使用session
        http.csrf().disable();
        // 开启跨域
        http.cors();
        // 基于token,所以不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 配置放行的资源和需要鉴权的资源
        http.authorizeRequests()
                .antMatchers(PASS_URL).permitAll()
                .anyRequest().authenticated();

        // 登录
        http.formLogin().loginPage("/login").loginProcessingUrl("/login");

        // 退出登录
        http.logout().logoutSuccessHandler(logoutSuccessHandler).logoutUrl("/logout");

        // 登陆参数json格式获取,json格式提交时可配置此类
        http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 解决 无法直接注入 AuthenticationManager
     *
     * @return AuthenticationManager
     * @throws Exception Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        //获取用户账号密码及权限信息
        return new UserDetailsServiceImpl();
    }

    /**
     * 配置认证方式等
     *
     * @param auth 身份验证
     * @throws Exception 异常
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 自定义密码校验,密码加盐时可使用此配置
        //auth.authenticationProvider(new PasswordCheckHandler(userDetailsService()));
        //配置认证方式
        auth.userDetailsService(userDetailsService()).passwordEncoder(bCryptPasswordEncoder());
    }

    /**
     * 加密方式
     *
     * @return {@link BCryptPasswordEncoder}
     */
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    LoginParamFilter loginFilter() throws Exception {
        LoginParamFilter loginFilter = new LoginParamFilter();
        loginFilter.setAuthenticationManager(authenticationManagerBean());
        // 登录成功
        loginFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
        // 登录失败
        loginFilter.setAuthenticationFailureHandler(loginFailureHandler);
        return loginFilter;
    }
}

10 前端vue项目登录验证

(1)用户名错误时

json响应

 页面响应

 

 (2)用户名正确,密码错误时 

json

 页面响应

(3)用户名,密码都正确

json

页面响应 

 至此,前后端分离下的security的登录成功!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值