文章目录
SpringSecurity && JWT
上一章SpringBoot项目实战(007)Spring Security(一)中,实现了Spring Security
的数据库认证。本章采用JWT实现无状态服务的认证和鉴权。
改造流程
- 服务改为STATELESS,不再使用session
- 数据库中
Users
表增加token
,相应代码调整。后期可以改为token存在redis中。 - 新增一个
JwtUtils
,封装常用的jwt
操作 - 初次请求登录时,获得一个新的
jwttoken
,并存入数据库。 - 再次请求API时,解析
jwttoken
,获得用户名,再从数据库载入权限。
无状态服务
现在微服务盛行,大部分RESTFUL API
都是采用STATELESS
的方式。比如在WebSecurityConfigurerAdapter
中:
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
......
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
......
}
......
}
加入以上代码后,即便你在login页面完成登录,也会在其他需要认证的页面弹出401,这是因为认证成功的SESSION并没有被保留。所以我们需要通过一个Token来传递信息。
数据库及mybatis调整
数据库新增字段Token
CREATE TABLE `Users` (
`UserId` int(11) NOT NULL AUTO_INCREMENT,
`UserName` varchar(45) NOT NULL,
`PassWord` varchar(100) NOT NULL,
`LockedFlag` tinyint(4) NOT NULL,
`Token` varchar(200) DEFAULT NULL,
PRIMARY KEY (`UserId`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
Bean
对应的,bean中添加一个字段:
//UserBean
@Data
@Accessors(chain = true)
@SuppressWarnings("serial")
public class UserBean implements Serializable {
private int userId;
private String userName;
private String passWord;
private int lockedFlag;
private String token;
}
//UserCondition
@Data
@Accessors(chain = true)
public class UserCondition extends BaseCondition {
private int userId;
private String userName;
private String passWord;
private int lockedFlag;
private String token;
@Override
public Class<?> getChildClass() {
return UserBean.class;
}
}
controller dao service
对应的controller(用于测试)、dao、service中增加方法getUserByToken:
//usercontroller
@RestController
@RequestMapping(value = "/user")
public class UserController extends BaseController<UserBean,UserCondition,IUserService>{
......
@RequestMapping(value = "/token/{token}", method = RequestMethod.GET)
public UserBean getUserByToken(@PathVariable(value = "token") String token) {
return baseService.getUserByToken(token);
}
}
//IUserService
public interface IUserService extends IBaseService<UserBean,UserCondition> {
UserBean findByName(String username);
UserBean getUserByToken(String token);
}
//UserServiceImpl
@Service
public class UserServiceImpl implements IUserService {
......
@Override
public UserBean getUserByToken(String token) {
return userDao.getUserByToken(token);
}
}
//userdao
public interface UserDao extends IBaseDao<UserBean,UserCondition> {
UserBean findByName(@Param("username") String username);
UserBean getUserByToken(@Param("token"