加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

SpringCloud之Security

发布时间:2020-12-15 07:14:21 所属栏目:Java 来源:网络整理
导读:Spring Security是Spring提供的一个安全框架,提供认证和授权功能,最主要的是它提供了简单的使用方式,同时又有很高的灵活性,简单,灵活,强大。 我个人博客系统采用的权限框架就是Spring Security,正好整合到SpringCloud里面。 一般系统里关于角色方面通

Spring Security是Spring提供的一个安全框架,提供认证和授权功能,最主要的是它提供了简单的使用方式,同时又有很高的灵活性,简单,灵活,强大。

我个人博客系统采用的权限框架就是Spring Security,正好整合到SpringCloud里面。

一般系统里关于角色方面通常有这么几张表,角色表、用户-角色表、菜单表、角色-菜单表等。

不过我个人博客系统主要以wordpress作为参考,沿用其12张表,如图:

?

?


一、导入Maven依赖

<properties>
       <jjwt.version>0.9.0</jjwt.version>
       <spring-security-jwt.version>1.0.9.RELEASE</spring-security-jwt.version>
</properties>
 <!-- springsecurity-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-security</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.security</groupId>
           <artifactId>spring-security-jwt</artifactId>
           <version>${spring-security-jwt.version}</version>
       </dependency>
       <dependency>
           <groupId>io.jsonwebtoken</groupId>
           <artifactId>jjwt</artifactId>
           <version>${jjwt.version}</version>
       </dependency>

二、编写Spring Security配置类

package com.springcloud.blog.admin.config;
import com.springcloud.blog.admin.security.UserAuthenticationProvider;
import com.springcloud.blog.admin.security.UserPermissionEvaluator;
import com.springcloud.blog.admin.security.handler.*;
import com.springcloud.blog.admin.security.jwt.JWTAuthenticationTokenFilter;
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.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;

/**
 * SpringSecurity配置类
 * @Author youcong
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限注解,默认是关闭的
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    *
     * 自定义登录成功处理器
     
    @Autowired
    private UserLoginSuccessHandler userLoginSuccessHandler;
    *
     * 自定义登录失败处理器
      UserLoginFailureHandler userLoginFailureHandler;
    *
     * 自定义注销成功处理器
      UserLogoutSuccessHandler userLogoutSuccessHandler;
    *
     * 自定义暂无权限处理器
      UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
    *
     * 自定义未登录的处理器
      UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
    *
     * 自定义登录逻辑验证器
      UserAuthenticationProvider userAuthenticationProvider;

    *
     * 加密方式
     * @Author youcong
     
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    *
     * 注入自定义PermissionEvaluator
      DefaultWebSecurityExpressionHandler userSecurityExpressionHandler(){
        DefaultWebSecurityExpressionHandler handler =  DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator( UserPermissionEvaluator());
        return handler;
    }

    *
     * 配置登录验证逻辑
     
    @Override
    protected void configure(AuthenticationManagerBuilder auth){
        这里可启用我们自己的登陆验证逻辑
        auth.authenticationProvider(userAuthenticationProvider);
    }
    *
     * 配置security的控制逻辑
     * @Author youcong
     * @Param  http 请求
      configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                 不进行权限验证的请求或资源(从配置文件中读取)
                .antMatchers(JWTConfig.antMatchers.split(",")).permitAll()
                 .antMatchers("/*").permitAll()
                 其他的需要登陆后才能访问
                .anyRequest().authenticated()
                .and()
                 配置未登录自定义处理类
                .httpBasic().authenticationEntryPoint(userAuthenticationEntryPointHandler)
                .and()
                 配置登录地址
                .formLogin()
                .loginProcessingUrl(/login/userLogin)
                 配置登录成功自定义处理类
                .successHandler(userLoginSuccessHandler)
                 配置登录失败自定义处理类
                .failureHandler(userLoginFailureHandler)
                .and()
                 配置登出地址
                .logout()
                .logoutUrl(/login/userLogout 配置用户登出自定义处理类
                .logoutSuccessHandler(userLogoutSuccessHandler)
                .and()
                 配置没有权限自定义处理类
                .exceptionHandling().accessDeniedHandler(userAuthAccessDeniedHandler)
                .and()
                 开启跨域
                .cors()
                .and()
                 取消跨站请求伪造防护
                .csrf().disable();
         基于Token不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
         禁用缓存
        http.headers().cacheControl();
         添加JWT过滤器
        http.addFilter( JWTAuthenticationTokenFilter(authenticationManager()));
    }
}

三、编写JWTConfig和application.yml增加jwt相关配置

package com.springcloud.blog.admin.config;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

*
 * JWT配置类
 * @Author youcong
 
@Getter
@Component
@ConfigurationProperties(prefix = jwt)
 JWTConfig {
    *
     * 密钥KEY
     */
    static String secret;
    *
     * TokenKey
      String tokenHeader;
    *
     * Token前缀字符
      String tokenPrefix;
    *
     * 过期时间
      Integer expiration;
    *
     * 不需要认证的接口
      String antMatchers;


     setSecret(String secret) {
        this.secret = secret;
    }

     setTokenHeader(String tokenHeader) {
        this.tokenHeader = tokenHeader;
    }

     setTokenPrefix(String tokenPrefix) {
        this.tokenPrefix = tokenPrefix;
    }

     setExpiration(Integer expiration) {
        this.expiration = expiration * 1000;
    }

     setAntMatchers(String antMatchers) {
        this.antMatchers = antMatchers;
    }


}

application.yml增加如下内容:

# JWT配置
jwt:
  # 密匙KEY
  secret: JWTSecret
  # HeaderKEY
  tokenHeader: Authorization
  # Token前缀字符
  tokenPrefix: challenger-
  # 过期时间 单位秒 1天后过期=86400 7天后过期=604800
  expiration: 86400
  # 配置不需要认证的接口
  antMatchers: /index*,/login/**,/favicon.ico
  # 有效时间
  validTime: 7

四、编写过滤器处理类

1.UserLoginSuccessHandler.java

package com.springcloud.blog.admin.security.handler;


import com.springcloud.blog.admin.config.JWTConfig;
import com.springcloud.blog.admin.security.entity.SelfUserEntity;
import com.springcloud.blog.admin.utils.AccessAddressUtil;
import com.springcloud.blog.admin.utils.JWTTokenUtil;
import com.springcloud.blog.admin.utils.RedisUtil;
import com.springcloud.blog.admin.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

*
 * @Description 登录成功处理类
 * @Author youcong
 
@Component
 UserLoginSuccessHandler implements AuthenticationSuccessHandler {


    *
     * 登录成功返回结果
     * @Author youcong
      onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,Authentication authentication){
         组装JWT
        SelfUserEntity selfUserEntity =  (SelfUserEntity) authentication.getPrincipal();
        String token = JWTTokenUtil.createAccessToken(selfUserEntity);
        token = JWTConfig.tokenPrefix + token;

         封装返回参数
        Map<String,Object> resultData = new HashMap<>();
        resultData.put(code",200);
        resultData.put(msg登录成功token2.UserLoginFailureHandler.java
package com.springcloud.blog.admin.security.handler;


import com.springcloud.blog.admin.utils.ResultUtil;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

*
 * @Description 登录失败处理类
 * @Author youcong
  UserLoginFailureHandler implements AuthenticationFailureHandler {
    *
     * 登录失败返回结果
     * @Author youcong
      onAuthenticationFailure(HttpServletRequest request,AuthenticationException exception){
         这些对于操作的处理类可以根据不同异常进行不同处理
        if (exception instanceof UsernameNotFoundException){
            System.out.println(【登录失败】"+exception.getMessage());
            ResultUtil.responseJson(response,ResultUtil.resultCode(500,1)">用户名不存在));
        }
         (exception instanceof LockedException){
            System.用户被冻结 (exception instanceof BadCredentialsException){
            System.密码错误));
        }
        ResultUtil.responseJson(response,1)">登录失败));
    }
}

3.UserLogoutSuccessHandler.java

package com.springcloud.blog.admin.security.handler;


import com.springcloud.blog.admin.utils.DateUtil;
import com.springcloud.blog.admin.utils.RedisUtil;
import com.springcloud.blog.admin.utils.ResultUtil;
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.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

*
 * 登出成功处理类
 * @Author youcong
  UserLogoutSuccessHandler implements LogoutSuccessHandler {
    

    *
     * 用户登出返回结果
     * 这里应该让前端清除掉Token
     * @Author youcong
      onLogoutSuccess(HttpServletRequest request,Authentication authentication){

        Map<String,1)">登出成功);
        SecurityContextHolder.clearContext();
        ResultUtil.responseJson(response,ResultUtil.resultSuccess(resultData));
    }
}

4.UserAuthAccessDeniedHandler.java

package com.springcloud.blog.admin.security.handler;
import com.springcloud.blog.admin.utils.ResultUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

*
 * @Description 暂无权限处理类
 * @Author youcong
  UserAuthAccessDeniedHandler implements AccessDeniedHandler {
    *
     * 暂无权限返回结果
     * @Author youcong
      handle(HttpServletRequest request,AccessDeniedException exception){
        ResultUtil.responseJson(response,1)">403,1)">未授权));
    }
}

5.UserAuthenticationEntryPointHandler.java

package com.springcloud.blog.admin.security.handler;


import com.springcloud.blog.admin.utils.ResultUtil;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

*
 * 用户未登录处理类
 * @Author youcong
  UserAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
    *
     * 用户未登录返回结果
     * @Author youcong
      commence(HttpServletRequest request,AuthenticationException exception){
        ResultUtil.responseJson(response,1)">401,1)">未登录));
    }
}

6.UserAuthenticationProvider.java

自定义登录验证这个类,需要根据实际情况重写。通常来说改动不大。

package com.springcloud.blog.admin.security;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.springcloud.blog.admin.entity.Usermeta;
import com.springcloud.blog.admin.entity.Users;
import com.springcloud.blog.admin.security.entity.SelfUserEntity;
import com.springcloud.blog.admin.service.UsermetaService;
import com.springcloud.blog.admin.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

*
 * 自定义登录验证
 *
 * @Author youcong
  UserAuthenticationProvider implements AuthenticationProvider {


    @Autowired
     UsersService usersService;

    @Autowired
     UsermetaService usermetaService;

    @Override
     Authentication authenticate(Authentication authentication) throws AuthenticationException {
         获取表单输入中返回的用户名
        String userName = (String) authentication.getPrincipal();
         获取表单中输入的密码
        String password = (String) authentication.getCredentials();
         查询用户是否存在
         SelfUserEntity userInfo = usersService.getUserInfo(userName);


        if (userInfo.getUsername() == null || userInfo.getUsername() == "") {
            throw new UsernameNotFoundException();
        }


         我们还要判断密码是否正确,这里我们的密码使用BCryptPasswordEncoder进行加密的
        if (! BCryptPasswordEncoder().matches(password,userInfo.getPassword())) {
            new BadCredentialsException(密码不正确);
        }
         还可以加一些其他信息的判断,比如用户账号已停用等判断
        if (userInfo.getStatus().equals(1)) {
            new LockedException(该用户已被冻结 角色集合
        Set<GrantedAuthority> authorities = new HashSet<>();

        EntityWrapper<Usermeta> roleWrapper = new EntityWrapper<>();
        roleWrapper.eq(user_idmeta_keywp_user_level);
         查询用户角色
        List<Usermeta> sysRoleEntityList = usermetaService.selectList(roleWrapper);
        for (Usermeta sysRoleEntity: sysRoleEntityList){
            authorities.add(new SimpleGrantedAuthority(ROLE_" + sysRoleEntity.getMetaValue()));
        }
        userInfo.setAuthorities(authorities);
         进行登录
         UsernamePasswordAuthenticationToken(userInfo,password,authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        true;
    }
}

7.UserPermissionEvaluator.java

package com.springcloud.blog.admin.security;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.springcloud.blog.admin.entity.Usermeta;
import com.springcloud.blog.admin.service.UsermetaService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

*
 * 自定义权限注解验证
 * @Author youcong
  UserPermissionEvaluator implements PermissionEvaluator {

    @Autowired
     UsermetaService usermetaService;

    *
     * hasPermission鉴权方法
     * 这里仅仅判断PreAuthorize注解中的权限表达式
     * 实际中可以根据业务需求设计数据库通过targetUrl和permission做更复杂鉴权
     * 当然targetUrl不一定是URL可以是数据Id还可以是管理员标识等,这里根据需求自行设计
     * @Author youcong
     * @Param  authentication  用户身份(在使用hasPermission表达式时Authentication参数默认会自动带上)
     * @Param  targetUrl  请求路径
     * @Param  permission 请求路径权限
     * @Return boolean 是否通过
      boolean hasPermission(Authentication authentication,Object targetUrl,Object permission) {
         获取用户信息
        Usermeta selfUserEntity =(Usermeta) authentication.getPrincipal();
         查询用户权限(这里可以将权限放入缓存中提升效率)
        Set<String> permissions = ();
        EntityWrapper<Usermeta> roleWrapper = );
        List<Usermeta> sysMenuEntityList = (Usermeta sysMenuEntity:sysMenuEntityList) {
            permissions.add(sysMenuEntity.getMetaValue());
        }
         权限对比
         (permissions.contains(permission.toString())){
            ;
        }
        ;
    }
    @Override
    false;
    }
}

五、编写实体类

package com.springcloud.blog.admin.security.entity;

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

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;

*
 * SpringSecurity用户的实体
 * 注意:这里必须要实现UserDetails接口
 *
 * @Author youcong
 */
 SelfUserEntity implements Serializable,UserDetails {

    private static final long serialVersionUID = 1L;

    *
     * 用户ID
      Long userId;
    *
     * 用户名
      String username;
    *
     * 密码
      String password;
    *
     * 状态
      String status;


    *
     * 显示名称
      String displayName;


    *
     * 用户参数
     private Map<String,String> userParamMap;


    *
     * 用户角色
     private Collection<GrantedAuthority> authorities;
    *
     * 账户是否过期
     private boolean isAccountNonExpired = ;
    *
     * 账户是否被锁定
     private boolean isAccountNonLocked = *
     * 证书是否过期
     private boolean isCredentialsNonExpired = *
     * 账户是否有效
     private boolean isEnabled = ;


    static long getSerialVersionUID() {
         serialVersionUID;
    }

     Long getUserId() {
         userId;
    }

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

    @Override
     String getUsername() {
         username;
    }

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

    @Override
     String getPassword() {
         password;
    }

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


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


     setEnabled(boolean enabled) {
        isEnabled = enabled;
    }

     setStatus(String status) {
        this.status = status;
    }

     String getStatus() {
         String getDisplayName() {
         displayName;
    }

     setDisplayName(String displayName) {
        this.displayName =public Map<String,1)"> getUserParamMap() {
         userParamMap;
    }

    void setUserParamMap(Map<String,1)"> userParamMap) {
        this.userParamMap = userParamMap;
    }

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

    @Override
     boolean isAccountNonExpired() {
         isAccountNonExpired;
    }

    @Override
     boolean isAccountNonLocked() {
         isAccountNonLocked;
    }

    @Override
     boolean isCredentialsNonExpired() {
         isCredentialsNonExpired;
    }

    @Override
     boolean isEnabled() {
         isEnabled;
    }


}

六、编写JWT接口请求拦截器

package com.springcloud.blog.admin.security.jwt;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.springcloud.blog.admin.config.JWTConfig;
import com.springcloud.blog.admin.security.entity.SelfUserEntity;
import com.springcloud.blog.admin.utils.CollectionUtil;
import com.springcloud.blog.admin.utils.JWTTokenUtil;
import com.springcloud.blog.admin.utils.RedisUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

*
 * JWT接口请求校验拦截器
 * 请求接口时会进入这里验证Token是否合法和过期
 *
 * @Author youcong
  JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {

     JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
     doFilterInternal(HttpServletRequest request,FilterChain filterChain) throws ServletException,IOException {
         获取请求头中JWT的Token
        String tokenHeader = request.getHeader(JWTConfig.tokenHeader);

        if (null != tokenHeader && tokenHeader.startsWith(JWTConfig.tokenPrefix)) {
            try {


                 截取JWT前缀
                String token = tokenHeader.replace(JWTConfig.tokenPrefix,1)">);
                 解析JWT
                Claims claims = Jwts.parser()
                        .setSigningKey(JWTConfig.secret)
                        .parseClaimsJws(token)
                        .getBody();
                 获取用户名
                String username = claims.getSubject();
                String userId = claims.getId();


                if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(userId)) {
                     获取角色
                    List<GrantedAuthority> authorities = new ArrayList<>();
                    String authority = claims.get(authorities).toString();
                    StringUtils.isEmpty(authority)) {
                        List<Map<String,String>> authorityMap = JSONObject.parSEObject(authority,List.);
                        for (Map<String,1)"> role : authorityMap) {
                            StringUtils.isEmpty(role)) {
                                authorities.add(new SimpleGrantedAuthority(role.authority)));
                            }
                        }
                    }
                    组装参数
                    SelfUserEntity selfUserEntity =  SelfUserEntity();
                    selfUserEntity.setUsername(claims.getSubject());
                    selfUserEntity.setUserId(Long.parseLong(claims.getId()));
                    selfUserEntity.setAuthorities(authorities);
                    UsernamePasswordAuthenticationToken authentication =  UsernamePasswordAuthenticationToken(selfUserEntity,userId,authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (ExpiredJwtException e) {
                System.Token过期);
            }  (Exception e) {
                System.Token无效);
            }
        }
        filterChain.doFilter(request,response);
        ;
    }
}

七、SpringSecurity用户的业务实现

package com.springcloud.blog.admin.security.service;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.springcloud.blog.admin.entity.Users;
import com.springcloud.blog.admin.security.entity.SelfUserEntity;
import com.springcloud.blog.admin.service.UsersService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

*
 * SpringSecurity用户的业务实现
 *
 * @Author youcong
  SelfUserDetailsService implements UserDetailsService {

    @Autowired
     UsersService usersService;

    *
     * 查询用户信息
     *
     * @Author youcong
     * @Param username  用户名
     * @Return UserDetails SpringSecurity用户信息
      SelfUserEntity loadUserByUsername(String username) throws UsernameNotFoundException {

        EntityWrapper<Users> wrapper = ();


        邮箱正则表达式
        String expr = ^([a-zA-Z0-9_-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.)|(([a-zA-Z0-9-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})$;

        是否为邮箱
         (username.matches(expr)) {
            wrapper.eq(user_emailelse {
            wrapper.eq(user_login 查询用户信息
        Users sysUserEntity = usersService.selectOne(wrapper);
        if (sysUserEntity != null 组装参数
            SelfUserEntity selfUserEntity =  SelfUserEntity();
            BeanUtils.copyProperties(sysUserEntity,selfUserEntity);
             selfUserEntity;
        }
        ;
    }
}

八、Spring Security常用注解

1.@Secured

当@EnableGlobalMethodSecurity(securedEnabled=true)的时候,@Secured可以使用。

@PostMapping(/helloUser)
@Secured({ROLE_normalROLE_admin})
 initDashboard() {
        Map<String,Object> result = ();
        result.put(ResponseDict.RESPONSE_TITLE_KEY,1)">仪表盘初始化);
        result.put(ResponseDict.RESPONSE_DATA_KEY,dashboardService.initDashboard());
         ResultUtil.resultSuccess(result);
    }

说明:拥有normal或者admin角色的用户都可以方法helloUser()方法。另外需要注意的是这里匹配的字符串需要添加前缀“ROLE_“。

2.@PreAuthorize

Spring的 @PreAuthorize/@PostAuthorize 注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制。

当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PreAuthorize可以使用:

@PostMapping(/initDashboard)
@PreAuthorize(hasRole('100') initDashboard() {
    Map<String,1)">();
    result.put(ResponseDict.RESPONSE_TITLE_KEY,1)">);
    result.put(ResponseDict.RESPONSE_DATA_KEY,dashboardService.initDashboard());
     ResultUtil.resultSuccess(result);
}

3.@PostAuthorize

@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证,适合验证带有返回值的权限,Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。

当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PostAuthorize可以使用:

@GetMapping(/getUserInfo)
@PostAuthorize( returnObject!=null &&  returnObject.username == authentication.name User getUserInfo() {
        Object pricipal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user;
        if(anonymousUser.equals(pricipal)) {
            user = ;
        } {
            user = (User) pricipal;
        }
         user;
}

九、测试

(1)登录测试,拿到token,如图:

?

?


(2)请求中如果不携带token的话,请求其它接口就会显示没有登录的提示,如图:

?

?


(3)正确的请求应当携带token,就像下面这样,如图:

?

?


(4)没有权限请求,如图:

?

?


(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读