版权声明:转载请注明出处 https://blog.csdn.net/chenmingxu438521/article/details/88633395
一、基础准备
参考资料:https://www.cnblogs.com/zls1218/p/8856347.html 感谢这位小伙伴的资料,你们可以参考下
1.pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
二、项目结构
三、自定义Shiroconfig
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
//配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("logout", "logout");
filterChainDefinitionMap.put("/user/login", "anon");
// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/user/**", "anon");
filterChainDefinitionMap.put("/**", "authc");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login.html");
//登录成功跳转的链接 (这个不知道怎么用,我都是自己实现跳转的)
shiroFilterFactoryBean.setSuccessUrl("/main.html");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//凭证匹配器,由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
@Bean
public UserRealm myShiroRealm(){
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return userRealm;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
//自动代理所有的advisor
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager());
return advisor;
}
/**
* 注册全局异常处理
* @return
*/
@Bean(name = "exceptionHandler")
public HandlerExceptionResolver handlerExceptionResolver() {
return new ExceptionHandler();
}
}
四、自定义UserReam
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
//授权,即权限验证,验证某个已认证的用户是否拥有某个权限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//在数据库中查询用户拥有的角色/权限
authorizationInfo.setRoles(userService.findRoles(username));
authorizationInfo.setStringPermissions(userService.findPermissions(username));
return authorizationInfo;
}
//验证,身份认证、登录,验证用户是不是拥有相应的身份
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
User user = userService.findByUsername(username);
if (user==null){
//没找到账户
throw new UnknownAccountException();
}
if (Boolean.TRUE.equals(user.getLocked())){
//账户被锁定
throw new LockedAccountException();
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(),
user.getPassword(),
//salt = username+salt
ByteSource.Util.bytes(user.getCredentialsSalt()),
getName()
);
return authenticationInfo;
}
}
五、创建各个逻辑代码
1.UserController.java
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public ModelAndView login(User loginUser,ServletRequest request){
ModelAndView view = new ModelAndView();
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUsername(),loginUser.getPassword());
if(!subject.isAuthenticated()){
subject.login(token);
}
//获取上一次请求路径
SavedRequest savedRequest = WebUtils.getSavedRequest(request);
String url = "";
if(savedRequest != null){
url = savedRequest.getRequestUrl();
}else{
url = "/main.html";
}
view.setViewName("redirect:"+url);
return view;
}
@RequestMapping("/register")
public ModelAndView add(User user){
ModelAndView view = new ModelAndView();
userService.createUser(user);
view.setViewName("redirect:/login.html");
return view;
}
@RequestMapping("/logout")
public String logout(User loginUser){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "已注销";
}
}
2.加密
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public ModelAndView login(User loginUser,ServletRequest request){
ModelAndView view = new ModelAndView();
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUsername(),loginUser.getPassword());
if(!subject.isAuthenticated()){
subject.login(token);
}
//获取上一次请求路径
SavedRequest savedRequest = WebUtils.getSavedRequest(request);
String url = "";
if(savedRequest != null){
url = savedRequest.getRequestUrl();
}else{
url = "/main.html";
}
view.setViewName("redirect:"+url);
return view;
}
@RequestMapping("/register")
public ModelAndView add(User user){
ModelAndView view = new ModelAndView();
userService.createUser(user);
view.setViewName("redirect:/login.html");
return view;
}
@RequestMapping("/logout")
public String logout(User loginUser){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "已注销";
}
}
3.UserServiceImpl.java
@Override
public void changePassword(Long userId, String newPassword) {
User user = userDao.findOne(userId);
user.setPassword(newPassword);
userDao.updateUser(user);
}
4.其他的我就不写了,具体的我会把源码贴出来,放到我的git上面,有需要的小伙伴可以去我的Git上面下载。
六、测试
1.启动项目
2.浏览器访问
3.注册,然后查看数据库中的表(我注册是cmx 密码123456)
4.然后再登陆
结果就出来了,这就是完成了登陆验证的功能。
下篇讲解用户的权限怎么去做。
七、代码存放的位置(下篇的代码也在这里了)