目录结构:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lxg.springboot</groupId>
<artifactId>springboot-security-oauth2</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<repositories>
<repository>
<id>aliyunRepository</id>
<name>myRepository</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<spring-security-oauth2.version>2.0.3.RELEASE</spring-security-oauth2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.7.RELEASE</version>
</dependency>
</dependencies>
</project>
application.properties
#web server
server.port=1130
#spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
#数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/test
#用户名
spring.datasource.username=root
#密码
spring.datasource.password=123456
#数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#自动更新
spring.jpa.properties.hibernate.hbm2ddl.auto=update
# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=1
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
MyUserDetailsService
package com.lxg.springboot.config;
import com.lxg.springboot.entity.Role;
import com.lxg.springboot.entity.User;
import com.lxg.springboot.entity.UserRole;
import com.lxg.springboot.service.UserRoleService;
import com.lxg.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/**
* Created by lxg
* on 2017/2/20.
*/
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private UserRoleService userRoleService;
/**
* 根据用户名获取登录用户信息
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("用户名:"+ username + "不存在!");
}
Collection<SimpleGrantedAuthority> collection = new HashSet<SimpleGrantedAuthority>();
Iterator<Role> iterator = user.getList().iterator();
while (iterator.hasNext()){
collection.add(new SimpleGrantedAuthority(iterator.next().getRole_name()));
}
return new org.springframework.security.core.userdetails.User(username,user.getPassword(),collection);
}
}
HelloWorldRestController
package com.lxg.springboot.controller;
import java.util.List;
import java.util.Objects;
import com.lxg.springboot.entity.User;
import com.lxg.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
@Controller
public class HelloWorldRestController {
@Autowired
UserService userService; //Service which will do all data retrieval/manipulation work
//-------------------Retrieve All Users--------------------------------------------------------
@PreAuthorize("hasRole('admin')")
@RequestMapping(value = "/user/", method = RequestMethod.GET)
@ResponseBody
public List<User> listAllUsers() {
List<User> users = userService.findAll();
if(users.isEmpty()){
return null;
}
return users;
}
@PreAuthorize("hasRole('user')")
@RequestMapping(value = "/one/", method = RequestMethod.GET)
@ResponseBody
public User one() {
User user = userService.findByUsername("user");
if(user == null){
return null;
}
return user;
}
//-------------------Retrieve Single User--------------------------------------------------------
/*@RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<User> getUser(@PathVariable("id") long id) {
System.out.println("Fetching User with id " + id);
User user = userService.findById(id);
if (user == null) {
System.out.println("User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}*/
//-------------------Create a User--------------------------------------------------------
/*@RequestMapping(value = "/user/", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
System.out.println("Creating User " + user.getName());
if (userService.isUserExist(user)) {
System.out.println("A User with name " + user.getName() + " already exist");
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}*/
//------------------- Update a User --------------------------------------------------------
/*@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) {
System.out.println("Updating User " + id);
User currentUser = userService.findById(id);
if (currentUser==null) {
System.out.println("User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
currentUser.setName(user.getName());
currentUser.setAge(user.getAge());
currentUser.setSalary(user.getSalary());
userService.updateUser(currentUser);
return new ResponseEntity<User>(currentUser, HttpStatus.OK);
}*/
//------------------- Delete a User --------------------------------------------------------
/*@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {
System.out.println("Fetching & Deleting User with id " + id);
User user = userService.findById(id);
if (user == null) {
System.out.println("Unable to delete. User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
userService.deleteUserById(id);
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}*/
//------------------- Delete All Users --------------------------------------------------------
/*@RequestMapping(value = "/user/", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteAllUsers() {
System.out.println("Deleting All Users");
userService.deleteAllUsers();
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}*/
}
Role
package com.lxg.springboot.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import static javax.persistence.GenerationType.IDENTITY;
/**
* Created by lxg
* on 2017/2/20.
*/
@Entity
@Table(name = "role")
public class Role implements Serializable{
private int id;
private String role_name;
@Id
@GeneratedValue(strategy = IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
}
User
package com.lxg.springboot.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import static javax.persistence.GenerationType.IDENTITY;
/**
* Created by lxg
* on 2017/2/20.
*/
@Entity
@Table(name = "user")
public class User implements Serializable {
private int id;
private String username;
private String password;
private List<Role> list = new ArrayList<Role>();
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@JoinTable(name="user_role",
joinColumns={ @JoinColumn(name="uid",referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="rid",referencedColumnName="id")})
public List<Role> getList() {
return list;
}
public void setList(List<Role> list) {
this.list = list;
}
@Id
@GeneratedValue(strategy = IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
UserRole
package com.lxg.springboot.entity;
import javax.persistence.*;
import java.io.Serializable;
import static javax.persistence.GenerationType.IDENTITY;
/**
* Created by lxg
* on 2017/2/20.
*/
@Entity
@Table(name = "user_role")
public class UserRole implements Serializable{
private int id;
private int uid;
private int rid;
@Id
@GeneratedValue(strategy = IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getRid() {
return rid;
}
public void setRid(int rid) {
this.rid = rid;
}
}
RoleRepository
package com.lxg.springboot.mapper;
import com.lxg.springboot.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* Created by lxg
* on 2017/2/20.
*/
@Repository
public interface RoleRepository extends JpaRepository<Role,Long> {
}
UserRepository
package com.lxg.springboot.mapper;
import com.lxg.springboot.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* Created by lxg
* on 2017/2/20.
*/
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
User findByUsername(String name);
}
UserRoleRepository
package com.lxg.springboot.mapper;
import com.lxg.springboot.entity.UserRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* Created by lxg
* on 2017/2/20.
*/
@Repository
public interface UserRoleRepository extends JpaRepository<UserRole,Long> {
List<UserRole> findByuid(int uid);
@Query(value = "select r.role_name from user_role ur left join role r on ur.rid=r.id where ur.uid = ?1",nativeQuery = true)
List<String> findRoleName(int uid);
}
AuthorizationServerConfiguration(核心配置)
package com.lxg.springboot.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
/**
* 认证服务器配置
* @author lxg
*
* 2017年2月17日上午10:50:04
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-trusted-client")//客户端ID
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit", "client_credentials")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")//授权用户的操作权限
.secret("secret")//密码
.accessTokenValiditySeconds(120)//token有效期为120秒
.refreshTokenValiditySeconds(600)
.redirectUris("http://example.com");//刷新token有效期为600秒
}
@Bean
public TokenStore tokenStore(){
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager)
// token生成方式
.accessTokenConverter(accessTokenConverter())
//接收GET和POST
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
// 开启/oauth/token_key验证端口无权限访问
.tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
oauthServer.addTokenEndpointAuthenticationFilter(new CorsFilter(corsConfigurationSource()));
}
/**
* 处理跨域问题
* @return
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "HEAD", "DELETE", "OPTION"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.addExposedHeader("Authorization");
configuration.addExposedHeader("Content-disposition");//文件下载消息头
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
OAuth2SecurityConfiguration(核心配置)
package com.lxg.springboot.security;
import com.lxg.springboot.config.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
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.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
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.redis.RedisTokenStore;
/**
* security配置
*
* @author lxg
*
* 2017年2月17日上午11:13:55
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private RedisConnectionFactory redisConnection;
@Bean
public MyUserDetailsService myUserDetailsService(){
return new MyUserDetailsService();
}
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(myUserDetailsService())
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
/*http
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();*/
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
http.formLogin().permitAll();
http.logout().permitAll().deleteCookies("JSESSIONID");
http.csrf().disable();
http.authorizeRequests()
.antMatchers( "/login").permitAll()
.anyRequest().authenticated();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public TokenStore tokenStore() {
return new RedisTokenStore(redisConnection);
}
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
ResourceServerConfiguration
package com.lxg.springboot.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* 资源服务器
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
resources.tokenServices(defaultTokenServices);
resources.resourceId(RESOURCE_ID).stateless(false);
}
@Bean
public JwtAccessTokenConverter accessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers().antMatchers("/user*/**")
.and().authorizeRequests()
.antMatchers("/user*/**").permitAll()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
UserService
package com.lxg.springboot.service;
import com.lxg.springboot.entity.User;
import java.util.List;
/**
* Created by lxg
* on 2017/2/21.
*/
public interface UserService {
User findByUsername(String name);
List<User> findAll();
}
UserRoleService
package com.lxg.springboot.service;
import java.util.List;
/**
* Created by lxg
* on 2017/2/21.
*/
public interface UserRoleService {
List<String> findRoles(int uid);
}
UserRoleServiceImpl
package com.lxg.springboot.service.impl;
import com.lxg.springboot.entity.UserRole;
import com.lxg.springboot.mapper.UserRoleRepository;
import com.lxg.springboot.service.UserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created by lxg
* on 2017/2/21.
*/
@Service
public class UserRoleServiceImpl implements UserRoleService {
@Autowired
private UserRoleRepository userRoleRepository;
@Override
public List<String> findRoles(int uid) {
List<String> list = userRoleRepository.findRoleName(uid);
return list;
}
}
UserServiceImpl
package com.lxg.springboot.service.impl;
import com.lxg.springboot.entity.User;
import com.lxg.springboot.mapper.UserRepository;
import com.lxg.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created by lxg
* on 2017/2/21.
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User findByUsername(String name) {
return userRepository.findByUsername(name);
}
@Override
public List<User> findAll() {
return userRepository.findAll();
}
}
JwtUtil(暂时未用到)
package com.lxg.springboot.util;
/**
* @author 小石潭记
* @date 2020/7/5 21:44
* @Description: ${todo}
*/
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
import java.util.HashMap;
public class JwtUtil {
/**
* 过期时间为15分钟
*/
private static final long EXPIRE_TIME = 15*60*1000;
/**
* token私钥
*/
private static final String TOKEN_SECRET = "frank_xbchen";
/**
* 生成签名,15分钟后过期
* @param username
* @param userId
* @return
*/
public static String sign(String username,String userId){
//过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
//私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//设置头信息
HashMap<String, Object> header = new HashMap<>(2);
header.put("typ", "JWT");
header.put("alg", "HS256");
//附带username和userID生成签名
return JWT.create().withHeader(header).withClaim("username",username)
.withClaim("userId",userId).withExpiresAt(date).sign(algorithm);
}
public static boolean verity(String token){
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (IllegalArgumentException e) {
return false;
} catch (JWTVerificationException e) {
return false;
}
}
}
PasswordTool
package com.lxg.springboot.util;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author 小石潭记
* @date 2020/7/5 19:09
* @Description: 加解密的工具
*/
public class PasswordTool {
public static void main(String[] args) {
String pass_admin = "admin";
String pass_123456 = "123456";
BCryptPasswordEncoder bcryptPasswordEncoder = new BCryptPasswordEncoder();
String hashPass1 = bcryptPasswordEncoder.encode(pass_admin);
System.out.println(hashPass1);
String p_admin = "$2a$10$cAVX9v/h/YhHlKGrMP4Xwuf2Buc1ksN35jCzw0Bov5zQzjfLEyPVC";
String hashPass2 = bcryptPasswordEncoder.encode(pass_123456);
System.out.println(hashPass2);
String p_123456 = "$2a$10$jH.e74/Oy41OfUsSgi3KQu5MlC/9ISytTS0mMl0YiXM0RdbfijmS.";
// 解密判断密码是否相等
boolean f = bcryptPasswordEncoder.matches("admin",p_admin);
System.out.println(f);
boolean f1 = bcryptPasswordEncoder.matches("123456",p_123456);
System.out.println(f1);
}
}
Application
package com.lxg.springboot;
import org.springframework.boot.SpringApplication;
/**
* Created by lxg
* on 2017/2/18.
*/
@org.springframework.boot.autoconfigure.SpringBootApplication
public class Application {
public static void main(String[] args){
new SpringApplication(Application.class).run(args);
}
}
db.sql
-- --------------------------------------------------------
-- 主机: 127.0.0.1
-- 服务器版本: 5.6.40 - MySQL Community Server (GPL)
-- 服务器操作系统: Win64
-- HeidiSQL 版本: 8.2.0.4675
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- 导出 test 的数据库结构
CREATE DATABASE IF NOT EXISTS `test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;
-- 导出 表 test.role 结构
CREATE TABLE IF NOT EXISTS `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- 正在导出表 test.role 的数据:~2 rows (大约)
DELETE FROM `role`;
/*!40000 ALTER TABLE `role` DISABLE KEYS */;
INSERT INTO `role` (`id`, `role_name`) VALUES
(1, 'ROLE_admin'),
(2, 'ROLE_user');
/*!40000 ALTER TABLE `role` ENABLE KEYS */;
-- 导出 表 test.user 结构
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- 正在导出表 test.user 的数据:~2 rows (大约)
DELETE FROM `user`;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` (`id`, `username`, `password`) VALUES
(1, 'admin', '$2a$10$jH.e74/Oy41OfUsSgi3KQu5MlC/9ISytTS0mMl0YiXM0RdbfijmS.'),
(2, 'user', '$2a$10$jH.e74/Oy41OfUsSgi3KQu5MlC/9ISytTS0mMl0YiXM0RdbfijmS.');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
-- 导出 表 test.user_role 结构
CREATE TABLE IF NOT EXISTS `user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`rid` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_q7oskmwmmyn5usc6cqsi2g28g` (`rid`),
KEY `FKe5x46iw9uaj34h12wkbvxj7k5` (`uid`),
CONSTRAINT `FKe5x46iw9uaj34h12wkbvxj7k5` FOREIGN KEY (`uid`) REFERENCES `user` (`id`),
CONSTRAINT `FKid0s4w8sbpgppnfro2ej3oana` FOREIGN KEY (`rid`) REFERENCES `role` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- 正在导出表 test.user_role 的数据:~2 rows (大约)
DELETE FROM `user_role`;
/*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
INSERT INTO `user_role` (`id`, `uid`, `rid`) VALUES
(1, 1, 1),
(2, 2, 2);
/*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
Oauth2 测试
1.密码模式获取token:localhost:1130/oauth/token
加上token访问:localhost:1130/user/?access_token=331cc443-4c62-4588-8d3d-75dbd8b0e12c(该接口需要admin权限,需要登录admin的账号,如果使用user账号,"error": "access_denied",
"error_description": "不允许访问")
刷新token:
localhost:1130/oauth/token?client_id=my-trusted-client&client_secret=secret&grant_type=refresh_token&refresh_token=2c819380-62ae-4cc9-9079-1e7bffb414a3
2.使用授权码获取token:
这里第一次好像需要登录,使用具体的账号密码登陆即可,如果使用的admin账号,就是admin的权限。
点击授权获取code码,这里的http://example.com是在代码里面配置的回调路径
接下使用code去获取token:
接下来使用token去访问接口:
localhost:1130/user/?access_token=d43099fe-8093-4152-b49e-990121199850
3.客户端模式获取token:
localhost:1130/oauth/token?client_id=my-trusted-client&client_secret=secret&grant_type=client_credentials
使用该token测试时,这里需要登陆,使用对应的账号密码登陆,admin账号就是admin权限
4.简化模式:
使用该token测试
localhost:1130/one/?access_token=190e38af-9265-4dae-ac39-33b194781f4e
该种模式,需要登录,直接使用上面的链接访问,然后会自动弹出login页面,使用对应的账号密码登陆即可。
Jwt的形式返回的token,获取方式和使用方式同上。