13-项目集成SpringSecurity-自定义用户详情服务Bean-2

SpringSecurity中的User类只有用户名、密码、权限信息三个用户详情字段

/**
 * Models core user information retrieved by a {@link UserDetailsService}.
 * <p>
 * Developers may use this class directly, subclass it, or write their own
 * {@link UserDetails} implementation from scratch.
 * <p>
 * {@code equals} and {@code hashcode} implementations are based on the {@code username}
 * property only, as the intention is that lookups of the same user principal object (in a
 * user registry, for example) will match where the objects represent the same user, not
 * just when all the properties (authorities, password for example) are the same.
 * <p>
 * Note that this implementation is not immutable. It implements the
 * {@code CredentialsContainer} interface, in order to allow the password to be erased
 * after authentication. This may cause side-effects if you are storing instances
 * in-memory and reusing them. If so, make sure you return a copy from your
 * {@code UserDetailsService} each time it is invoked.
 *
 * @author Ben Alex
 * @author Luke Taylor
 */
public class User implements UserDetails, CredentialsContainer {

	private String password;

	private final String username;

	private final Set<GrantedAuthority> authorities;

    //省略其他代码
}

为了可以设置更多的属性,新建com.itheima.stock.security.user.LoginUserDetail 

package com.itheima.stock.security.user;

import com.itheima.stock.vo.resp.PermissionRespNodeVo;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.List;

/**
 * 自定义用户详情类
 */
@Data
public class LoginUserDetail implements UserDetails {
    private String username;
    private String password;
    private List<GrantedAuthority> authorities;
    /**
     * 账户没有过期
     */
    private boolean isAccountNonExpired=true;
    /**
     * 账号没有锁定
     */
    private boolean isAccountNonLocked=true;
    /**
     * 密码没有过期
     */
    private   boolean isCredentialsNonExpired=true;
    /**
     * 账户是否禁用
     *  true:没有禁用
     */
    boolean isEnabled= true;
    //自定义字段
    /**
     * 用户ID
     */
    private Long id;
    /**
     * 电话
     */
    private String phone;
    /**
     * 昵称
     */
    private String nickName;

    /**
     * 真实姓名
     */
    private String realName;

    /**
     * 性别(1.男 2.女)
     */
    private Integer sex;

    /**
     * 账户状态(1.正常 2.锁定 )
     */
    private Integer status;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 权限树,不包含按钮相关权限信息
     */
    private List<PermissionRespNodeVo> menus;

    /**
     * 前端按钮权限集合
     */
    private List<String> permissions;
}

 新建com.itheima.stock.security.service.LoginUserDetailService

package com.itheima.stock.security.service;


import com.google.common.base.Strings;
import com.itheima.stock.mapper.SysRoleMapper;
import com.itheima.stock.mapper.SysUserMapperExt;
import com.itheima.stock.pojo.entity.SysPermission;
import com.itheima.stock.pojo.entity.SysRole;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.security.user.LoginUserDetail;
import com.itheima.stock.service.PermissionService;
import com.itheima.stock.vo.resp.PermissionRespNodeVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
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 java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 定义获取用户详情服务Bean
 */
@Service("userDetailsService")
public class LoginUserDetailService implements UserDetailsService {
    @Autowired
    private SysUserMapperExt sysUserMapperExt;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private SysRoleMapper sysRoleMapper;

    /**
     * 根据用户名获取用户详情:用户名,密码,权限集合等
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询查询数据库中用户详情
        SysUser dbUser = sysUserMapperExt.findUserByUserName(username);
        if (dbUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        //获取指定用户的权限集合 添加获取侧边栏数据和按钮权限的结合信息
        List<SysPermission> permissions = permissionService.getPermissionByUserId(dbUser.getId());
        List<SysRole> roles = sysRoleMapper.getRoleByUserId(dbUser.getId());
        //获取树状权限菜单数据
        List<PermissionRespNodeVo> menus = permissionService.getTree(permissions, 0l, true);
        //获取菜单按钮集合
        List<String> authBtnPerms = permissions.stream()
                .filter(per -> !Strings.isNullOrEmpty(per.getCode()) && per.getType() == 3)
                .map(per -> per.getCode()).collect(Collectors.toList());
        List<String> ps = new ArrayList<String>();
        //获取security的权限标识
        List<String> pers = permissions.stream()
                .filter(per -> StringUtils.isNotBlank(per.getPerms()))
                .map(per -> per.getPerms())
                .collect(Collectors.toList());
        ps.addAll(pers);
        List<String> rs = roles.stream().map(r -> "ROLE_" + r.getName()).collect(Collectors.toList());
        ps.addAll(rs);
        String[] psArray = ps.toArray(new String[ps.size()]);
        //将用户拥有的权限标识转化为权限对象
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(psArray);
        //构建用户详情服务对象
        LoginUserDetail userDetail = new LoginUserDetail();
        //将dbUser的属性复制到userDetail
        BeanUtils.copyProperties(dbUser, userDetail);
        userDetail.setMenus(menus);
        userDetail.setPermissions(authBtnPerms);
        userDetail.setAuthorities(authorities);
        return userDetail;
    }
}

修改com.itheima.stock.security.filter.JwtLoginAuthenticationFilter

  /**
     *
     * @param request
     * @param response
     * @param chain  过滤器链
     * @param authResult 认证对象
     * method.
     * @throws IOException
     * @throws ServletException
     */
    @Override
    //认证成功时的回调方法
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        LoginUserDetail userDetail = (LoginUserDetail) authResult.getPrincipal();
        String username = userDetail.getUsername();
        Collection<GrantedAuthority> authorities = userDetail.getAuthorities();
        //生成token
        String tokenStr = JwtTokenUtil.createToken(username, authorities.toString());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        //构建响应实体对象
        LoginRespVoExt respVoExt = new LoginRespVoExt();
        BeanUtils.copyProperties(userDetail,respVoExt);
        respVoExt.setAccessToken(tokenStr);
        R<LoginRespVoExt> ok = R.ok(respVoExt);
        response.getWriter().write(new ObjectMapper().writeValueAsString(ok));
    }

    @Override
    //认证失败时的回调方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        R<Object> error = R.error(ResponseCode.ERROR);
        response.getWriter().write(new ObjectMapper().writeValueAsString(error));
    }

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的翠花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值