文章目录

  • 1.配置Swagger
  • 2.spring security配置
  • 3.用户校验逻辑
    • 注册和登录接口
  • dao层 service层 pojo层
  • 4.加密验证逻辑
  • 5.生成令牌逻辑
    • 身份验证提供者:
    • 自定义令牌对象:
  • 6.登录认证过滤器:
  • 7.JwtToken工具类:
    • security工具类
  • 8.权限封装:
  • 9.用户模型:
  • 10.测试生成令牌
  • 11.测试用户权限

1.配置Swagger

为了方便测试首先在swagger config中配置加入令牌项,配置token作为请求头部参数:

@Configuration
@EnableSwagger2
public class SwaggerConfig
{/** 是否开启swagger */@Value("true")private boolean enabled;/*** 创建API*/@Beanpublic Docket createRestApi() {// 添加请求参数,我们这里把token作为请求头部参数传入后端ParameterBuilder parameterBuilder = new ParameterBuilder();List<Parameter> parameters = new ArrayList<Parameter>();parameterBuilder.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); //关键是这里,将token作为了请求头参数parameters.add(parameterBuilder.build());return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(enabled).select().apis(RequestHandlerSelectors.basePackage("com.english.english_vision")).paths(PathSelectors.any()).build().globalOperationParameters(parameters);}private ApiInfo apiInfo() {.....}
}

这样写了以后运行会发现在请求时多了一行token:

在登陆成功后会返回token,用这个token去请求其他接口即可

2.spring security配置

新建securityconfig类

@Primary
//由于报There is more than one bean of 'UserDetailsService' 所以我在类上面加了@primary 不过不加也不影响运行
@Configuration
@EnableWebSecurity    // 开启Spring Security
@EnableGlobalMethodSecurity(prePostEnabled = true)    // 开启权限注解,如:@PreAuthorize注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;//UserDetailsService 是rpingsecurity中自己的接口@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {// 使用自定义身份验证组件auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 禁用 csrf, 由于使用的是JWT,我们这里不需要csrfhttp.cors().and().csrf().disable().authorizeRequests()// 跨域预检请求.antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/user/login").permitAll()//这里的路径可以自己配置.antMatchers("/security/save").permitAll()//注册.antMatchers("/security/login").permitAll()//登录// swagger.antMatchers("/swagger-ui.html").permitAll().antMatchers("/swagger-resources/**").permitAll().antMatchers("/v2/api-docs").permitAll().antMatchers("/webjars/springfox-swagger-ui/**").permitAll()// 服务监控.antMatchers("/actuator/**").permitAll()// 其他所有请求需要身份认证.anyRequest().authenticated();// 退出登录处理器http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());// token验证过滤器http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);}@Bean@Overridepublic AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}}

3.用户校验逻辑

spring security整合jwt的代码较多,目录如下:

注册和登录接口

@RestController
@RequestMapping("/security")
@Api(tags = {"安全登录接口"})
public class UserSecurityController {@Autowiredprivate IUserSecurityService securityService;@Autowiredprivate AuthenticationManager authenticationManager;@ApiOperation(value = "注册或者修改用户")@PostMapping(value = "/save")public ResponseResult save(UserSecurity record) {boolean save=false;UserSecurity userSecurity = securityService.getById(record.getId());if (record.getPassword() != null) {String salt = PasswordUtils.getSalt();if (userSecurity == null) {// 新增用户if (securityService.selectByName(record.getName()) != null) {return ResponseResult.error("用户名已存在!");}String password = PasswordUtils.encode(record.getPassword(), salt);               record.setSalt(salt);record.setPassword(password);} else {// 修改用户, 且修改了密码if (!record.getPassword().equals(userSecurity.getPassword())) {String password = PasswordUtils.encode(record.getPassword(), salt);record.setSalt(salt);record.setPassword(password);}}save = securityService.save(record);}if (save) {return ResponseResult.success(record);} else {return ResponseResult.error(ResponseEnum.ERROR);}}@ApiOperation(value = "用户登录")@PostMapping(value = "/login")public ResponseResult login(@RequestBody LoginBean loginBean, HttpServletRequest request){String username = loginBean.getName();String password = loginBean.getPassword();
// 用户信息UserSecurity user = securityService.selectByName(username);// 账号不存在、密码错误if (user == null) {return ResponseResult.error("账号不存在");}     if (!PasswordUtils.matches(user.getSalt(), password, user.getPassword())) {return ResponseResult.error("密码不正确");}// 系统登录认证JwtAuthenticatioToken token = SecurityUtils.login(request, username, password, authenticationManager);return ResponseResult.success(token);}
}

加密是:
String password = PasswordUtils.encode(record.getPassword(), salt);
验证是:
if (!PasswordUtils.matches(user.getSalt(), password, user.getPassword())) {
}
加密时只会对明文密码进行加密然后与数据库进行匹配,不会对密文解密,这样更加安全。

dao层 service层 pojo层

public interface IUserSecurityService extends IService<UserSecurity> {UserSecurity selectByName(String username);Set<String> findPermissions(String userName);
}@Service
public class UserSecurityServiceImpl extends ServiceImpl<UserSecurityMapper, UserSecurity> implements IUserSecurityService {@Autowired
private UserSecurityMapper securityMapper;@Overridepublic UserSecurity selectByName(String username) {return securityMapper.selectByName(username);}@Overridepublic Set<String> findPermissions(String userName) {return securityMapper.findPermissions(userName);}
}

loginbean:

/*** @Author* @Description 登录接口封装对象* @Date**/
@Data
public class LoginBean {private String name;private String password;// private String captcha;}

用户pojo:

@NoArgsConstructor
@AllArgsConstructor
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_user_security")
@ApiModel("用户安全管理")
public class UserSecurity implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(name = "id", value = "用户id", dataType = "Integer")@TableId(value = "id", type = IdType.AUTO)private Integer id=null;@ApiModelProperty(name = "name", value = "用户名", dataType = "String")private String name;@ApiModelProperty(name = "password", value = "用户密码", dataType = "String")private String password;@ApiModelProperty(name = "salt", value = "密码盐", dataType = "String")private String salt;@ApiModelProperty(name = "perm", value = "用户权限", dataType = "String")private String perm;
}

mapper:

@Mapper
public interface UserSecurityMapper extends BaseMapper<UserSecurity> {@Select("select * from t_user_security where name=#{username}")UserSecurity selectByName(String username);@Select("select perm from t_user_security where name=#{username}")Set<String> findPermissions(String userName);
}

4.加密验证逻辑

/*** 密码工具类*/
public class PasswordUtils {/*** 匹配密码* @param salt 盐* @param rawPass 明文 * @param encPass 密文* @return*/public static boolean matches(String salt, String rawPass, String encPass) {return new PasswordEncoder(salt).matches(encPass, rawPass);}/*** 明文密码加密* @param rawPass 明文* @param salt* @return*/public static String encode(String rawPass, String salt) {return new PasswordEncoder(salt).encode(rawPass);}/*** 获取加密盐* @return*/public static String getSalt() {return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 20);}
}

加密:

public class PasswordEncoder {private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d","e", "f" };private final static String MD5 = "MD5";private final static String SHA = "SHA";private Object salt;private String algorithm;public PasswordEncoder(Object salt) {this(salt, MD5);}public PasswordEncoder(Object salt, String algorithm) {this.salt = salt;this.algorithm = algorithm;}/*** 密码加密* @param rawPass* @return*/public String encode(String rawPass) {String result = null;try {System.out.println("加密"+rawPass);MessageDigest md = MessageDigest.getInstance(algorithm);// 加密后的字符串result = byteArrayToHexString(md.digest(mergePasswordAndSalt(rawPass).getBytes("utf-8")));} catch (Exception ex) {}return result;}/*** 密码匹配验证* @param encPass 密文* @param rawPass 明文* @return*/public boolean matches(String encPass, String rawPass) {String pass1 = "" + encPass;String pass2 = encode(rawPass);System.out.println("密文"+encPass);System.out.println(rawPass+"加密后"+pass2);return pass1.equals(pass2);}private String mergePasswordAndSalt(String password) {if (password == null) {password = "";}if ((salt == null) || "".equals(salt)) {return password;} else {return password + "{" + salt.toString() + "}";}}/*** 转换字节数组为16进制字串* * @param b*            字节数组* @return 16进制字串*/private String byteArrayToHexString(byte[] b) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++) {resultSb.append(byteToHexString(b[i]));}return resultSb.toString();}/*** 将字节转换为16进制* @param b* @return*/private static String byteToHexString(byte b) {int n = b;if (n < 0)n = 256 + n;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}

5.生成令牌逻辑

身份验证提供者:

package com.english.english_vision.config.springSecurity;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;/*** @Author* @Description 身份验证提供者* @Date 10.19**/
public class JwtAuthenticationProvider extends DaoAuthenticationProvider {public JwtAuthenticationProvider(UserDetailsService userDetailsService) {setUserDetailsService(userDetailsService);}@Overrideprotected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {if (authentication.getCredentials() == null) {logger.debug("Authentication failed: no credentials provided");throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}String presentedPassword = authentication.getCredentials().toString();String salt = ((JwtUserDetails) userDetails).getSalt();// 覆写密码验证逻辑if (!new PasswordEncoder(salt).matches(userDetails.getPassword(), presentedPassword)) {logger.debug("Authentication failed: password does not match stored value");throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}}}

自定义令牌对象:

package com.english.english_vision.config.springSecurity;import java.util.Collection;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;public class JwtAuthenticatioToken extends UsernamePasswordAuthenticationToken {private static final long serialVersionUID = 1L;private String token;public JwtAuthenticatioToken(Object principal, Object credentials){super(principal, credentials);}public JwtAuthenticatioToken(Object principal, Object credentials, String token){super(principal, credentials);this.token = token;}public JwtAuthenticatioToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities, String token) {super(principal, credentials, authorities);this.token = token;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}public static long getSerialversionuid() {return serialVersionUID;}}

JwtAuthenticatioToken继承自UsernamePasswordAuthenticationToken,
UsernamePasswordAuthenticationToken继承AbstractAuthenticationToken实现Authentication
所以当在页面中输入用户名和密码之后首先会进入到UsernamePasswordAuthenticationToken验(Authentication),
然后生成的Authentication会被交由AuthenticationManager来进行管理,而AuthenticationManager管理一系列的AuthenticationProvider,每一个Provider都会通UserDetailsService和UserDetail来返回一个以UsernamePasswordAuthenticationToken实现的带用户名和密码以及权限的Authentication

6.登录认证过滤器:

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {@Autowiredpublic JwtAuthenticationFilter(AuthenticationManager authenticationManager) {super(authenticationManager);}
//AuthenticationManager这个接口方法入参和返回值的类型都是Authentication。该接口的作用是对用户的未授信凭据进行认证,认证通过则返回授信状态的凭据,否则将抛出认证异常AuthenticationException。@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {// 获取token, 并检查登录状态SecurityUtils.checkAuthentication(request);chain.doFilter(request, response);}}

BasicAuthenticationFilter:当一个HTTP请求中包含一个名字为Authorization的头部,并且其值格式是Basic xxx时,该Filter会认为这是一个BASIC authorization头部,其中xxx部分应该是一个base64编码的{username}:{password}字符串。比如用户名/密码分别为 admin/secret, 则对应的该头部是 : Basic YWRtaW46c2VjcmV0 。

该过滤器会从 HTTP BASIC authorization头部解析出相应的用户名和密码然后调用AuthenticationManager进行认证,成功的话会把认证了的结果写入到SecurityContextHolder中SecurityContext的属性authentication上面。同时还会做其他一些处理,比如Remember Me相关处理等等。

7.JwtToken工具类:

public class JwtTokenUtils implements Serializable {private static final long serialVersionUID = 1L;/*** 用户名称*/private static final String USERNAME = Claims.SUBJECT;/*** 创建时间*/private static final String CREATED = "created";/*** 权限列表*/private static final String AUTHORITIES = "authorities";/*** 密钥*/private static final String SECRET = "abcdefgh";/*** 有效期12小时*/private static final long EXPIRE_TIME = 12 * 60 * 60 * 1000;/*** 生成令牌** @param userDetails 用户* @return 令牌*/public static String generateToken(Authentication authentication) {Map<String, Object> claims = new HashMap<>(3);claims.put(USERNAME, SecurityUtils.getUsername(authentication));claims.put(CREATED, new Date());claims.put(AUTHORITIES, authentication.getAuthorities());return generateToken(claims);}/*** 从数据声明生成令牌** @param claims 数据声明* @return 令牌*/private static String generateToken(Map<String, Object> claims) {Date expirationDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, SECRET).compact();}/*** 从令牌中获取用户名** @param token 令牌* @return 用户名*/public static String getUsernameFromToken(String token) {String username;try {Claims claims = getClaimsFromToken(token);username = claims.getSubject();} catch (Exception e) {username = null;}return username;}/*** 根据请求令牌获取登录认证信息* @param token 令牌* @return 用户名*/public static Authentication getAuthenticationeFromToken(HttpServletRequest request) {Authentication authentication = null;// 获取请求携带的令牌String token = JwtTokenUtils.getToken(request);if(token != null) {// 请求令牌不能为空if(SecurityUtils.getAuthentication() == null) {// 上下文中Authentication为空Claims claims = getClaimsFromToken(token);if(claims == null) {return null;}String username = claims.getSubject();if(username == null) {return null;}if(isTokenExpired(token)) {return null;}Object authors = claims.get(AUTHORITIES);List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();if (authors != null && authors instanceof List) {for (Object object : (List) authors) {authorities.add(new GrantedAuthorityImpl((String) ((Map) object).get("authority")));}}authentication = new JwtAuthenticatioToken(username, null, authorities, token);} else {if(validateToken(token, SecurityUtils.getUsername())) {// 如果上下文中Authentication非空,且请求令牌合法,直接返回当前登录认证信息authentication = SecurityUtils.getAuthentication();}}}return authentication;}/*** 从令牌中获取数据声明** @param token 令牌* @return 数据声明*/private static Claims getClaimsFromToken(String token) {Claims claims;try {claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();} catch (Exception e) {claims = null;}return claims;}/*** 验证令牌* @param token* @param username* @return*/public static Boolean validateToken(String token, String username) {String userName = getUsernameFromToken(token);return (userName.equals(username) && !isTokenExpired(token));}/*** 刷新令牌* @param token* @return*/public static String refreshToken(String token) {String refreshedToken;try {Claims claims = getClaimsFromToken(token);claims.put(CREATED, new Date());refreshedToken = generateToken(claims);} catch (Exception e) {refreshedToken = null;}return refreshedToken;}/*** 判断令牌是否过期** @param token 令牌* @return 是否过期*/public static Boolean isTokenExpired(String token) {try {Claims claims = getClaimsFromToken(token);Date expiration = claims.getExpiration();return expiration.before(new Date());} catch (Exception e) {return false;}}/*** 获取请求token* @param request* @return*/public static String getToken(HttpServletRequest request) {String token = request.getHeader("Authorization");String tokenHead = "Bearer ";if(token == null) {token = request.getHeader("token");} else if(token.contains(tokenHead)){token = token.substring(tokenHead.length());} if("".equals(token)) {token = null;}return token;}}

security工具类

public class SecurityUtils {/*** 系统登录认证* @param request* @param username* @param password* @param authenticationManager* @return*/public static JwtAuthenticatioToken login(HttpServletRequest request, String username, String password, AuthenticationManager authenticationManager) {JwtAuthenticatioToken token = new JwtAuthenticatioToken(username, password);token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));// 执行登录认证过程Authentication authentication = authenticationManager.authenticate(token);// 认证成功存储认证信息到上下文SecurityContextHolder.getContext().setAuthentication(authentication);// 生成令牌并返回给客户端token.setToken(JwtTokenUtils.generateToken(authentication));return token;}/*** 获取令牌进行认证* @param request*/public static void checkAuthentication(HttpServletRequest request) {// 获取令牌并根据令牌获取登录认证信息Authentication authentication = JwtTokenUtils.getAuthenticationeFromToken(request);// 设置登录认证信息到上下文SecurityContextHolder.getContext().setAuthentication(authentication);}/*** 获取当前用户名* @return*/public static String getUsername() {String username = null;Authentication authentication = getAuthentication();if(authentication != null) {Object principal = authentication.getPrincipal();if(principal != null && principal instanceof UserDetails) {username = ((UserDetails) principal).getUsername();}}return username;}/*** 获取用户名* @return*/public static String getUsername(Authentication authentication) {String username = null;if(authentication != null) {Object principal = authentication.getPrincipal();if(principal != null && principal instanceof UserDetails) {username = ((UserDetails) principal).getUsername();}}return username;}/*** 获取当前登录信息* @return*/public static Authentication getAuthentication() {if(SecurityContextHolder.getContext() == null) {return null;}Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return authentication;}}

8.权限封装:

public class GrantedAuthorityImpl implements GrantedAuthority {private static final long serialVersionUID = 1L;private String authority;public GrantedAuthorityImpl(String authority) {this.authority = authority;}public void setAuthority(String authority) {this.authority = authority;}@Overridepublic String getAuthority() {return this.authority;}
}

9.用户模型:

public class JwtUserDetails implements UserDetails {private static final long serialVersionUID = 1L;private String username;private String password;private String salt;private Collection<? extends GrantedAuthority> authorities;JwtUserDetails(String username, String password, String salt, Collection<? extends GrantedAuthority> authorities) {this.username = username;this.password = password;this.salt = salt;this.authorities = authorities;}@Overridepublic String getUsername() {return username;}@JsonIgnore@Overridepublic String getPassword() {return password;}public String getSalt() {return salt;}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return authorities;}@JsonIgnore@Overridepublic boolean isAccountNonExpired() {return true;}@JsonIgnore@Overridepublic boolean isAccountNonLocked() {return true;}@JsonIgnore@Overridepublic boolean isCredentialsNonExpired() {return true;}@JsonIgnore@Overridepublic boolean isEnabled() {return true;}
}

10.测试生成令牌

配置好以后先注册:

返回注册成功的信息:

然后测试登录:

结果:

可以看到返回的token,复制下来然后用这个token测试其他接口即可

11.测试用户权限

首先在不加权限注解时测试这个接口:

    @ApiOperation(value="管理员添加某个单词")@PostMapping("admin/uploadword")public ResponseResult uploadWord(@RequestParam("wordfile")MultipartFile file,Word word) throws IOException {System.out.println("my CopyrightYear:"+new Myconfig().getCopyrightYear());String Wordpath = uploadUtils.upload(new Myconfig().getWordPath(),file);
word.setImg(Wordpath);
if(wordService.insert(word)>0)
{return ResponseResult.success(word);
}
else {return ResponseResult.error(ResponseEnum.ERROR);
}}

用刚刚生成的令牌进行测试:

可以看到添加成功:

现在在这个接口方法上加上权限注解:
@PreAuthorize(“hasAuthority(‘sys::manage’)”) ,重新运行:
由于刚刚登录的用户权限是sys::use,所以无法访问这个接口:

现在重新登录一个有sys::manage权限的用户,获得token,再次访问这个接口:

访问成功。

参考:https://blog.csdn.net/andy_zhang2007/article/details/84920910

https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1319904585363980289&__biz=MzUzMzQ2MDIyMA==#wechat_redirect

用spring security设置用户jwt令牌和设置接口访问权限案例相关推荐

  1. 基于 Spring Security OAuth2和 JWT 构建保护微服务系统

    我们希望自己的微服务能够在用户登录之后才可以访问,而单独给每个微服务单独做用户权限模块就显得很弱了,从复用角度来说是需要重构的,从功能角度来说,也是欠缺的.尤其是前后端完全分离之后,我们的用户信息不一 ...

  2. JWT实战 Spring Security Oauth2整合JWT 整合SSO单点登录

    文章目录 一.JWT 1.1 什么是JWT 1.2 JWT组成 头部(header) 载荷(payload) 签名(signature) 如何应用 1.3 JJWT 快速开始 创建token toke ...

  3. 使用Spring Security Oauth2 和 JWT保护微服务--Uaa授权服务器的编写

    学习自深入理解微服务 采用Spring Security OAuth2 和 JWT的方式,Uaa服务只需要验证一次,返回JWT.返回的JWT包含了用户的所有信息,包括权限信息 从三个方面讲解: JWT ...

  4. Spring Security OAuth2整合JWT

    文章目录 1. Spring Security 与 OAuth2 2. Spring Security OAuth2的配置和使用 ①:引入依赖 ②:配置 spring security ③:配置授权服 ...

  5. 《深入理解 Spring Cloud 与微服务构建》第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统

    <深入理解 Spring Cloud 与微服务构建>第十八章 使用 Spring Security OAuth2 和 JWT 保护微服务系统 文章目录 <深入理解 Spring Cl ...

  6. Spring Security:身份验证令牌Authentication介绍与Debug分析

    在Spring Security中,通过Authentication来封装用户的验证请求信息,Authentication可以是需要验证和已验证的用户请求信息封装.接下来,博主介绍Authentica ...

  7. 3.Spring Security 自定义用户认证

    Spring Security自定义用户认证 自定义认证过程 自定义认证的过程需要实现Spring Security提供的UserDetailService接口,该接口只有一个抽象方法loadUser ...

  8. 基于 Spring Security 搭建用户权限系统(二) - 自定义配置

    说明 本文的目的是如何基于 Spring Security 去扩展实现一个基本的用户权限模块, 内容会覆盖到 Spring Security 常用的配置. 文中涉及到的业务代码是不完善的, 甚至会存在 ...

  9. 服务器2003共享文件夹设置密码,win2003 server r2 设置不需要密码验证的共享文件访问权限(即匿名访问)...

    设置不需要密码验证的共享文件访问权限,也即匿名访问共享文件,方法如下: 默认情况,在同一工作组模式下,访问Windows 2003 server机器中共享的文件夹时,由于本地安全策略的限制,在输入UN ...

最新文章

  1. 70页论文,图灵奖得主Yoshua Bengio一作:「生成流网络」拓展深度学习领域
  2. 分库分表技术演进最佳实践-修订篇
  3. 使用IntelliJ IDEA看源码的时候,如何在优雅的查看类继承关系...【看这篇就够了】
  4. java windows域_域环境中的windows软件安装
  5. 程序员最讨厌的100件事,瞬间笑喷了,哈哈~~
  6. 平庸技术流,用 WebApi +AngularJS 实现网络爬虫
  7. 求剁手的分享,如何简单开发js图表
  8. CLR 4.0 有哪些新东西? What's new in CLR 4.0--类型嵌入 Type embedding
  9. Nginx valid_referer 防盗链
  10. spring入门——注入demo
  11. 全面升级,淘宝/天猫api接口大全
  12. 中南大学计算机学院羽毛球赛,我校第四届“四海一家亲”羽毛球邀请赛成功举行...
  13. 体验数学之美——泛函
  14. windows2012计算机在桌面显示,Windows2012 如何在桌面上显示”我的电脑”
  15. 1957:【12NOIP普及组】质因数分解
  16. MyExcel.net 使用手册
  17. SNI(Server Name Indication)
  18. JavaFX应用程序图标
  19. 【Cocos2D-x 3.5实战】坦克大战(2)游戏开始界面
  20. 教你如何合并pdf文件

热门文章

  1. mit 6.824 Distributed System
  2. mysql的FIQ怎么安装_MySQL数据库设计总结
  3. 大庆师范学院计算机系徐媛老师,大庆师范学院课程表(未添加英语课).xls
  4. 操作系统读写者问题实验报告_基于S3C2410微处理器和操作系统实现光电测量仿真检测系统的设计...
  5. html标签table的使用,HTML标签之table
  6. 深度学习和目标检测系列教程 11-300:小麦数据集训练Faster-RCNN模型
  7. 十六、深入Python字符串
  8. 2022年预训练的下一步是什么?
  9. NeurIPS 2021 | 微软研究院提出CLUES,用于NLU的少样本学习评估
  10. Swin Transformer升级版来了!30亿参数,刷榜多项视觉任务