栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security 使用核心

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security 使用核心

1.导入依赖

    
        org.springframework.cloud
        spring-cloud-starter-oauth2
    
    
        org.springframework.security
        spring-security-jwt
        1.0.10.RELEASE
    

2.认证服务配置   

package com.itheima.auth.config;

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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;


@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;


    @Autowired
    private AuthenticationManager authenticationManager;



    
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    
    @Bean
    public UserDetailsService userDetailsService(){
        //在内存中提供自定义的用户名 密码
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        //在内存中自定义用户名称:jack 密码:jack 权限:p1
        manager.createUser(User.withUsername("third").password(passwordEncoder().encode("third")).authorities("user:query").build());

        manager.createUser(User.withUsername("jack").password(passwordEncoder().encode("jack")).authorities("p1").build());
        manager.createUser(User.withUsername("rose").password(passwordEncoder().encode("rose")).authorities("p2").build());
        return manager;
    }

    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //客户端信息暂存储在内存中,也可改为security提供的表存储
        //授权码模式下需要的客户端信息如下
        clients.inMemory()
                .withClient("third_client")  //客户端标识
                    .secret(passwordEncoder().encode("third_secret"))  //客户端的秘钥
                    .authorizedGrantTypes("authorization_code")
                    .autoApprove(true)
                    .scopes("all")
                    //.autoApprove("all")
                    .redirectUris("http://www.baidu.com")  //设置回调地址
                //密码模式需要的客户端信息


                .and()
                    .withClient("app_client")  //客户端标识
                    .secret(passwordEncoder().encode("app_secret"))  //客户端的秘钥
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("all") //设置回调地址

                .and()
                    .withClient("pc_client")
                    .secret(passwordEncoder().encode("pc_secret"))
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("all");
    }





    
    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service = new DefaultTokenServices();
        //是否支持刷新令牌
        service.setSupportRefreshToken(true);
        //令牌存储
        service.setTokenStore(tokenStore);
        // 令牌有效期单位秒,默认默认12小时  设置为1周
        service.setAccessTokenValiditySeconds(604800);
        // 刷新令牌默认单位秒  默认30天 设置为3周
        service.setRefreshTokenValiditySeconds(1814400);
        return service;
    }




    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager)
                .tokenServices(tokenService());
    }


    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.allowFormAuthenticationForClients();  //支持密码模式下表单登录
    }
}

3.token加密方式配置

package com.happyu.auth.config;

import jdk.nashorn.internal.parser.Token;
import org.junit.Before;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import java.security.KeyPair;

@Configuration
public class TokenConfig {

    //对称加密采用秘钥
    private static final String secret = "itcast_auth";

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource("oauth2.jks"), "itcast".toCharArray()).getKeyPair("oauth2");
        jwtAccessTokenConverter.setKeyPair(keyPair);
//        jwtAccessTokenConverter.setSigningKey(secret);
        return jwtAccessTokenConverter;
    }

    
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
}

4.密码模式下需要:用户认证时需要的认证管理和用户信息来源

package com.happyu.auth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
      
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
   

}

5.配置认证器

package com.happyu.auth.integration.authenticator;

import com.happyu.sys.dto.CompanyUserDTO;

import javax.servlet.http.HttpServletRequest;


public interface LoginHandler {

    
    CompanyUserDTO queryUser(HttpServletRequest request);



    
    boolean support(HttpServletRequest request);
}

6.自定义UserDetailService

package com.happyu.auth.integration.service;


import cn.hutool.core.collection.CollectionUtil;
import com.happyu.auth.integration.authenticator.LoginHandler;
import com.happyu.common.threadlocals.UserHolder;
import com.happyu.common.util.BeanHelper;
import com.happyu.common.util.JsonUtils;
import com.happyu.common.vo.UserInfo;
import com.happyu.sys.dto.CompanyUserDTO;
import com.happyu.sys.entity.Function;
import com.happyu.sys.entity.Role;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;


@Slf4j
@Component
public class MyUserDetailsService implements UserDetailsService {

    
    @Autowired
    private List loginHandlers;


    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("调用到自定义详情服务MyUserDetailsService--查询用户信息");
        //1.获取用户提交认证方式
        //1.1 如果在普通类中获取请求参数 采用RequestContextHolder请求上下文对象
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //1.2 转为ServletRequestAttributes
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        //1.3 获取请求对象 进一步 获取请求参数
        HttpServletRequest request = servletRequestAttributes.getRequest();
        log.info("认证参数:"+request.getParameter("username") +", "+request.getParameter("auth_type"));

        //2.根据客户端认证方式,选择一个认证器进行 获取数据库中 员工信息
        //选择认证器
        LoginHandler loginHandler = chooseLoginHandler(request);
        CompanyUserDTO companyUserDTO = loginHandler.queryUser(request);

        //3.封装框架要求的返回结果 UserDetails 用户详情服务
        //3.1 封装用户权限信息
        List authorities = this.getAuthorities(companyUserDTO);
        if (CollectionUtils.isEmpty(authorities)) {
            //如果用户没有权限 增加 游客 角色
            authorities.add(new SimpleGrantedAuthority("ROLE_USER_TOURIST"));
        }

        //3.2 User对象参数一:生成jwt令牌中 user_name 属性值 问题:将来资源服务器无法得到用户ID标识
        //3.3 解决 将CompanyUserDTO转为 自定义对象:UserInfo
        UserInfo userInfo = BeanHelper.copyProperties(companyUserDTO, UserInfo.class);
        //将用户信息存入userholder
        UserHolder.setUser(userInfo);
        return new User(JsonUtils.toJsonStr(userInfo), companyUserDTO.getPassword(), authorities);
        //x.后续框架还会继续进行校验用户信息,客户端信息是否合法 ,最终才会根据用户信息产生令牌
    }


    
    private List getAuthorities(CompanyUserDTO companyUserDTO) {
        //1.封装角色权限
        List authorities = new ArrayList<>();
        List roleList = companyUserDTO.getSysRoles();
        if (CollectionUtil.isNotEmpty(roleList)) {
            for (Role role : roleList) {
                GrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role.getRoleName());
                authorities.add(simpleGrantedAuthority);
            }
        }
        //2.封装权限
        List functionList = companyUserDTO.getSysFunctions();
        if (CollectionUtil.isNotEmpty(functionList)) {
            for (Function function : functionList) {
                GrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(function.getName());
                authorities.add(simpleGrantedAuthority);
            }
        }
        return authorities;
    }


    
    private LoginHandler chooseLoginHandler(HttpServletRequest request) {
        //1.遍历认证器集合
        for (LoginHandler loginHandler : loginHandlers) {
            //2.每个认证器都有support方法 只要support返回true 直接返回当前实例对象
            boolean support = loginHandler.support(request);
            //2.1 进入某个方法实现
            if (support) {
                return loginHandler;
            }
        }
        throw new OAuth2Exception("不支持当前认证方式");
    }
}

6.在需要使用认证的微服务上添加资源配置和token配置

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/592558.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号