Spring Security

Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。

项目代码片段

记一次项目中使用的Spring security进行权限验证。admin,distrAdmin,reseller这三个权限为例。

安装mysqld服务器,输入命令:mysqld --install,启动mysql服务:net start mysql
加入依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

控制层:AuthController.java

@Slf4j
@RestController
@RequestMapping("/user")
@Api(value = "web管理页面,用户认证 login")
public class AuthController {
    @Autowired
    private AuthService authService;
    @PostMapping(value = "/login")
    @ApiOperation(value = "用户登陆", notes = "User")
    public ResponseEntity<?> login(@RequestBody @Valid UserVo userVo) {
        return authService.login(userVo);
    }
    @PostMapping(value = "/logout")
    @ApiOperation(value = "用户登出", notes = "User")
    @PreAuthorize("hasAnyRole('admin', 'distrAdmin', 'distrOperator', 'reseller')")
    public ResponseEntity<?> logout(@ApiIgnore @AuthenticationPrincipal UserBrief brief) {
        return authService.logout(brief);
    }
    @GetMapping(value = "/me")
    @ApiOperation(value = "用户认证", notes = "User")
    @PreAuthorize("hasAnyRole('admin', 'distrAdmin', 'distrOperator', 'reseller')")
    public ResponseEntity<?> me(@ApiIgnore @AuthenticationPrincipal UserBrief user) {
        return authService.me(user);
    }
}

AuthService.java
AuthServiceImpl.java

@Service
@Slf4j
public class AuthServiceImpl implements AuthService {
    private static final String DEFAUL_AUTHORITY_PREFIX = "ROLE_";
    @Autowired
    private DomainPasswordEncoder passwordEncoder;
    @Autowired
    private UserService userService;
    @Override
    public ResponseEntity<?> login(UserVo userVo) {
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUserName, userVo.getName()));
        if (ComUtil.isNull(user) || user.getUserType().isAppUser()) {
            throwBadRequest(LOGIN_FAIL);
        }
        boolean isMatch = passwordEncoder.match(userVo.getPassword(), user.getPassword());
        if (!isMatch) {
            throwBadRequest(LOGIN_FAIL);
        }
        Date now = new Date();
        //set login state: On=1 setting Sign in status On=1
        user.setStatus(Constant.MGR_USER_ON);
        String token = GenerationSequenceUtil.generateUUID("").substring(0, 16);
        userService.lambdaUpdate().set(User::getStatus, Constant.MGR_USER_ON)
                .set(User::getToken, token)
                .set(User::getTokenExpireDate, DateTimeUtil.addDays(now, 7))
                .eq(User::getId, user.getId()).update();
        String sessionKey = DesUtil.encrypt(String.format("%s%s", token, user.getUserName()));
        return ok(new UserLoginVo(user.getUserType(), sessionKey));
    }

    @Override
    public ResponseEntity<?> logout(UserBrief brief) {
        log.info("logout:{u:{}-{}}", brief.getId(), brief.getUserName());
        userService.lambdaUpdate().set(User::getStatus, Constant.APP_USER_OFF)
                .set(User::getToken, null)
                .set(User::getTokenExpireDate, null)
                .eq(User::getId, brief.getId()).update();
        return ok().build();
    }

    @Override
    public ResponseEntity<?> me(UserBrief user) {
        User found = userService.getById(user.getId());
        UserMeVo me = new UserMeVo(found.getUserType(), found.getDistrId(), found.getResellerId());
        return ok(me);
    }

    @Override
    public Authentication checkLogin(String userName) {
        User auth = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUserName, userName)
                .gt(User::getTokenExpireDate,new Date()));
        if(ComUtil.isEmpty(auth)){
            return null;
        }
        return buildAuthentication(auth, auth.getToken());
    }

    private Authentication buildAuthentication(User user, String token) {
        List<GrantedAuthority> authorities = Lists.newArrayList(
                new SimpleGrantedAuthority(DEFAUL_AUTHORITY_PREFIX + user.getUserType().name()));
        PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(user.toBrief(),
                user.getPassword(), authorities);
        authentication.setDetails(token);
        return authentication;
    }
}

TokenAuthenticationProvider.java

public class TokenAuthenticationProvider implements AuthenticationProvider {
    public TokenAuthenticationProvider() {
    }
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Optional<String> username = (Optional) authentication.getPrincipal();
        Optional<String> token = (Optional) authentication.getCredentials();
        emptyValidation(username, token);
        Class cls = null;
        Object resObj = null;
        try {
            cls = Class.forName("jp.co.tenfeetwright.sum.dmc.service.impl.AuthServiceImpl");
            Object obj = SpringUtil.getBean("authServiceImpl", cls);
            Method mth = ReflectionUtils.findMethod(obj.getClass(), "checkLogin", String.class);
            resObj = ReflectionUtils.invokeMethod(mth, obj, username.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(ComUtil.isEmpty(resObj)){
            throw new BadCredentialsException("Invalid token or token expired");
        }
        Authentication result = (Authentication) resObj;
        Optional<Object> auth = Optional.ofNullable(resObj);
        if (!auth.isPresent() || auth.get() == null) {
            throw new BadCredentialsException("Invalid token or token expired");
        }
        if (!result.getDetails().equals(token.get())) {
            throw new BadCredentialsException("Invalid token or token expired");
        }
        return result;
    }

    private void emptyValidation(Optional<String> username, Optional<String> token) {
        if (!username.isPresent() || username.get().isEmpty()) {
            throw new BadCredentialsException("Invalid token");
        }
        if (!token.isPresent() || token.get().isEmpty()) {
            throw new BadCredentialsException("Invalid token");
        }
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(PreAuthenticatedAuthenticationToken.class);
    }
}

注意:因为没有使用过这个,在之前写过的一个访问/login的页面跳转现在不起作用了(包括其他的接口也都被拦截,无法访问),就是因为security内置了一个login页面。
以上代码不全,截取的项目中的代码。

学习Demo

以下是我写的一个可用的Demo,自取:
https://download.csdn.net/download/weixin_45044097/13104660

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值